15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2005, Google Inc. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// All rights reserved. 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Redistribution and use in source and binary forms, with or without 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// modification, are permitted provided that the following conditions are 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// met: 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// * Redistributions of source code must retain the above copyright 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// notice, this list of conditions and the following disclaimer. 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// * Redistributions in binary form must reproduce the above 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// copyright notice, this list of conditions and the following disclaimer 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in the documentation and/or other materials provided with the 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// distribution. 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// * Neither the name of Google Inc. nor the names of its 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// contributors may be used to endorse or promote products derived from 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// this software without specific prior written permission. 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// --- 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// All Rights Reserved. 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Author: Maxim Lifantsev 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "config.h" 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <fcntl.h> // for O_RDONLY (we use syscall to do actual reads) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string.h> 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <errno.h> 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_UNISTD_H 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <unistd.h> 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_MMAP 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/mman.h> 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_PTHREAD 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <pthread.h> 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/stat.h> 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/types.h> 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <time.h> 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <assert.h> 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(HAVE_LINUX_PTRACE_H) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <linux/ptrace.h> 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_SYS_SYSCALL_H 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/syscall.h> 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(_WIN32) || defined(__CYGWIN__) || defined(__CYGWIN32__) || defined(__MINGW32__) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <wtypes.h> 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <winbase.h> 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef ERROR // windows defines these as macros, which can cause trouble 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef max 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef min 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector> 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map> 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set> 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm> 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <functional> 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <gperftools/heap-checker.h> 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/googleinit.h" 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <gperftools/stacktrace.h> 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/commandlineflags.h" 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/elfcore.h" // for i386_regs 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/thread_lister.h" 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "heap-profile-table.h" 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/low_level_alloc.h" 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "malloc_hook-inl.h" 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <gperftools/malloc_hook.h> 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <gperftools/malloc_extension.h> 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "maybe_threads.h" 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "memory_region_map.h" 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/spinlock.h" 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/sysinfo.h" 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_allocator.h" 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using std::string; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using std::basic_string; 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using std::pair; 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using std::map; 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using std::set; 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using std::vector; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using std::swap; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using std::make_pair; 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using std::min; 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using std::max; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using std::less; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using std::char_traits; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If current process is being ptrace()d, 'TracerPid' in /proc/self/status 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// will be non-zero. 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool IsDebuggerAttached(void) { // only works under linux, probably 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char buf[256]; // TracerPid comes relatively earlier in status output 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int fd = open("/proc/self/status", O_RDONLY); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (fd == -1) { 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; // Can't tell for sure. 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int len = read(fd, buf, sizeof(buf)); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool rc = false; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (len > 0) { 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *const kTracerPid = "TracerPid:\t"; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf[len - 1] = '\0'; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char *p = strstr(buf, kTracerPid); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (p != NULL) { 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rc = (strncmp(p + strlen(kTracerPid), "0\n", 2) != 0); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) close(fd); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rc; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This is the default if you don't link in -lprofiler 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" { 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ATTRIBUTE_WEAK PERFTOOLS_DLL_DECL bool ProfilingIsEnabledForAllThreads(); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ProfilingIsEnabledForAllThreads() { return false; } 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//---------------------------------------------------------------------- 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Flags that control heap-checking 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//---------------------------------------------------------------------- 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEFINE_string(heap_check, 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnvToString("HEAPCHECK", ""), 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "The heap leak checking to be done over the whole executable: " 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "\"minimal\", \"normal\", \"strict\", " 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "\"draconian\", \"as-is\", and \"local\" " 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) " or the empty string are the supported choices. " 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "(See HeapLeakChecker_InternalInitStart for details.)"); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEFINE_bool(heap_check_report, true, "Obsolete"); 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEFINE_bool(heap_check_before_constructors, 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) true, 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "deprecated; pretty much always true now"); 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEFINE_bool(heap_check_after_destructors, 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnvToBool("HEAP_CHECK_AFTER_DESTRUCTORS", false), 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "If overall heap check is to end after global destructors " 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "or right after all REGISTER_HEAPCHECK_CLEANUP's"); 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEFINE_bool(heap_check_strict_check, true, "Obsolete"); 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEFINE_bool(heap_check_ignore_global_live, 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnvToBool("HEAP_CHECK_IGNORE_GLOBAL_LIVE", true), 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "If overall heap check is to ignore heap objects reachable " 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "from the global data"); 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEFINE_bool(heap_check_identify_leaks, 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnvToBool("HEAP_CHECK_IDENTIFY_LEAKS", false), 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "If heap check should generate the addresses of the leaked " 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "objects in the memory leak profiles. This may be useful " 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "in tracking down leaks where only a small fraction of " 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "objects allocated at the same stack trace are leaked."); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEFINE_bool(heap_check_ignore_thread_live, 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnvToBool("HEAP_CHECK_IGNORE_THREAD_LIVE", true), 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "If set to true, objects reachable from thread stacks " 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "and registers are not reported as leaks"); 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEFINE_bool(heap_check_test_pointer_alignment, 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnvToBool("HEAP_CHECK_TEST_POINTER_ALIGNMENT", false), 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Set to true to check if the found leak can be due to " 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "use of unaligned pointers"); 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Alignment at which all pointers in memory are supposed to be located; 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// use 1 if any alignment is ok. 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// heap_check_test_pointer_alignment flag guides if we try the value of 1. 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The larger it can be, the lesser is the chance of missing real leaks. 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const size_t kPointerSourceAlignment = sizeof(void*); 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEFINE_int32(heap_check_pointer_source_alignment, 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnvToInt("HEAP_CHECK_POINTER_SOURCE_ALIGNMENT", 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kPointerSourceAlignment), 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Alignment at which all pointers in memory are supposed to be " 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "located. Use 1 if any alignment is ok."); 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A reasonable default to handle pointers inside of typical class objects: 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Too low and we won't be able to traverse pointers to normally-used 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// nested objects and base parts of multiple-inherited objects. 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Too high and it will both slow down leak checking (FindInsideAlloc 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in HaveOnHeapLocked will get slower when there are large on-heap objects) 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and make it probabilistically more likely to miss leaks 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of large-sized objects. 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int64 kHeapCheckMaxPointerOffset = 1024; 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEFINE_int64(heap_check_max_pointer_offset, 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnvToInt("HEAP_CHECK_MAX_POINTER_OFFSET", 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kHeapCheckMaxPointerOffset), 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Largest pointer offset for which we traverse " 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "pointers going inside of heap allocated objects. " 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Set to -1 to use the actual largest heap object size."); 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEFINE_bool(heap_check_run_under_gdb, 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnvToBool("HEAP_CHECK_RUN_UNDER_GDB", false), 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "If false, turns off heap-checking library when running under gdb " 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "(normally, set to 'true' only when debugging the heap-checker)"); 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEFINE_int32(heap_check_delay_seconds, 0, 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Number of seconds to delay on-exit heap checking." 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) " If you set this flag," 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) " you may also want to set exit_timeout_seconds in order to" 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) " avoid exit timeouts.\n" 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "NOTE: This flag is to be used only to help diagnose issues" 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) " where it is suspected that the heap checker is reporting" 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) " false leaks that will disappear if the heap checker delays" 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) " its checks. Report any such issues to the heap-checker" 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) " maintainer(s)."); 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEFINE_int32(heap_check_error_exit_code, 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnvToInt("HEAP_CHECK_ERROR_EXIT_CODE", 1), 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Exit code to return if any leaks were detected."); 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//---------------------------------------------------------------------- 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEFINE_string(heap_profile_pprof, 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnvToString("PPROF_PATH", "pprof"), 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "OBSOLETE; not used"); 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEFINE_string(heap_check_dump_directory, 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EnvToString("HEAP_CHECK_DUMP_DIRECTORY", "/tmp"), 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Directory to put heap-checker leak dump information"); 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//---------------------------------------------------------------------- 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// HeapLeakChecker global data 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//---------------------------------------------------------------------- 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Global lock for all the global data of this module. 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SpinLock heap_checker_lock(SpinLock::LINKER_INITIALIZED); 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//---------------------------------------------------------------------- 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Heap profile prefix for leak checking profiles. 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Gets assigned once when leak checking is turned on, then never modified. 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const string* profile_name_prefix = NULL; 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Whole-program heap leak checker. 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Gets assigned once when leak checking is turned on, 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// then main_heap_checker is never deleted. 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static HeapLeakChecker* main_heap_checker = NULL; 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Whether we will use main_heap_checker to do a check at program exit 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// automatically. In any case user can ask for more checks on main_heap_checker 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// via GlobalChecker(). 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool do_main_heap_check = false; 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The heap profile we use to collect info about the heap. 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This is created in HeapLeakChecker::BeforeConstructorsLocked 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// together with setting heap_checker_on (below) to true 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and registering our new/delete malloc hooks; 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// similarly all are unset in HeapLeakChecker::TurnItselfOffLocked. 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static HeapProfileTable* heap_profile = NULL; 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If we are doing (or going to do) any kind of heap-checking. 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool heap_checker_on = false; 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// pid of the process that does whole-program heap leak checking 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static pid_t heap_checker_pid = 0; 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If we did heap profiling during global constructors execution 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool constructor_heap_profiling = false; 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// RAW_VLOG level we dump key INFO messages at. If you want to turn 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// off these messages, set the environment variable PERFTOOLS_VERBOSE=-1. 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int heap_checker_info_level = 0; 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//---------------------------------------------------------------------- 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// HeapLeakChecker's own memory allocator that is 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// independent of the normal program allocator. 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//---------------------------------------------------------------------- 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Wrapper of LowLevelAlloc for STL_Allocator and direct use. 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We always access this class under held heap_checker_lock, 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// this allows us to in particular protect the period when threads are stopped 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// at random spots with ListAllProcessThreads by heap_checker_lock, 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// w/o worrying about the lock in LowLevelAlloc::Arena. 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We rely on the fact that we use an own arena with an own lock here. 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class HeapLeakChecker::Allocator { 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void Init() { 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_DCHECK(heap_checker_lock.IsHeld(), ""); 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_DCHECK(arena_ == NULL, ""); 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) arena_ = LowLevelAlloc::NewArena(0, LowLevelAlloc::DefaultArena()); 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void Shutdown() { 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_DCHECK(heap_checker_lock.IsHeld(), ""); 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!LowLevelAlloc::DeleteArena(arena_) || alloc_count_ != 0) { 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_LOG(FATAL, "Internal heap checker leak of %d objects", alloc_count_); 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static int alloc_count() { 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_DCHECK(heap_checker_lock.IsHeld(), ""); 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return alloc_count_; 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void* Allocate(size_t n) { 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_DCHECK(arena_ && heap_checker_lock.IsHeld(), ""); 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* p = LowLevelAlloc::AllocWithArena(n, arena_); 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (p) alloc_count_ += 1; 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return p; 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void Free(void* p) { 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_DCHECK(heap_checker_lock.IsHeld(), ""); 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (p) alloc_count_ -= 1; 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LowLevelAlloc::Free(p); 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void Free(void* p, size_t /* n */) { 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Free(p); 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // destruct, free, and make *p to be NULL 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) template<typename T> static void DeleteAndNull(T** p) { 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*p)->~T(); 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Free(*p); 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *p = NULL; 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) template<typename T> static void DeleteAndNullIfNot(T** p) { 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*p != NULL) DeleteAndNull(p); 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static LowLevelAlloc::Arena* arena_; 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static int alloc_count_; 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)LowLevelAlloc::Arena* HeapLeakChecker::Allocator::arena_ = NULL; 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int HeapLeakChecker::Allocator::alloc_count_ = 0; 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//---------------------------------------------------------------------- 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// HeapLeakChecker live object tracking components 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//---------------------------------------------------------------------- 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Cases of live object placement we distinguish 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum ObjectPlacement { 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MUST_BE_ON_HEAP, // Must point to a live object of the matching size in the 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // heap_profile map of the heap when we get to it 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IGNORED_ON_HEAP, // Is a live (ignored) object on heap 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MAYBE_LIVE, // Is a piece of writable memory from /proc/self/maps 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IN_GLOBAL_DATA, // Is part of global data region of the executable 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) THREAD_DATA, // Part of a thread stack and a thread descriptor with TLS 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) THREAD_REGISTERS, // Values in registers of some thread 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Information about an allocated object 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct AllocObject { 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const void* ptr; // the object 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uintptr_t size; // its size 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ObjectPlacement place; // where ptr points to 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AllocObject(const void* p, size_t s, ObjectPlacement l) 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : ptr(p), size(s), place(l) { } 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// All objects (memory ranges) ignored via HeapLeakChecker::IgnoreObject 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Key is the object's address; value is its size. 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef map<uintptr_t, size_t, less<uintptr_t>, 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STL_Allocator<pair<const uintptr_t, size_t>, 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapLeakChecker::Allocator> 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) > IgnoredObjectsMap; 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static IgnoredObjectsMap* ignored_objects = NULL; 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// All objects (memory ranges) that we consider to be the sources of pointers 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to live (not leaked) objects. 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// At different times this holds (what can be reached from) global data regions 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and the objects we've been told to ignore. 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// For any AllocObject::ptr "live_objects" is supposed to contain at most one 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// record at any time. We maintain this by checking with the heap_profile map 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of the heap and removing the live heap objects we've handled from it. 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This vector is maintained as a stack and the frontier of reachable 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// live heap objects in our flood traversal of them. 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef vector<AllocObject, 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STL_Allocator<AllocObject, HeapLeakChecker::Allocator> 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) > LiveObjectsStack; 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static LiveObjectsStack* live_objects = NULL; 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A special string type that uses my allocator 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef basic_string<char, char_traits<char>, 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STL_Allocator<char, HeapLeakChecker::Allocator> 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) > HCL_string; 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A placeholder to fill-in the starting values for live_objects 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// for each library so we can keep the library-name association for logging. 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef map<HCL_string, LiveObjectsStack, less<HCL_string>, 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STL_Allocator<pair<const HCL_string, LiveObjectsStack>, 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapLeakChecker::Allocator> 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) > LibraryLiveObjectsStacks; 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static LibraryLiveObjectsStacks* library_live_objects = NULL; 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Value stored in the map of disabled address ranges; 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// its key is the end of the address range. 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We'll ignore allocations with a return address in a disabled range 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// if the address occurs at 'max_depth' or less in the stack trace. 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct HeapLeakChecker::RangeValue { 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uintptr_t start_address; // the start of the range 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_depth; // the maximal stack depth to disable at 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef map<uintptr_t, HeapLeakChecker::RangeValue, less<uintptr_t>, 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STL_Allocator<pair<const uintptr_t, HeapLeakChecker::RangeValue>, 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapLeakChecker::Allocator> 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) > DisabledRangeMap; 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The disabled program counter address ranges for profile dumping 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that are registered with HeapLeakChecker::DisableChecksFromToLocked. 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static DisabledRangeMap* disabled_ranges = NULL; 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Set of stack tops. 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// These are used to consider live only appropriate chunks of the memory areas 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that are used for stacks (and maybe thread-specific data as well) 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// so that we do not treat pointers from outdated stack frames as live. 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef set<uintptr_t, less<uintptr_t>, 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STL_Allocator<uintptr_t, HeapLeakChecker::Allocator> 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) > StackTopSet; 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static StackTopSet* stack_tops = NULL; 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A map of ranges of code addresses for the system libraries 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that can mmap/mremap/sbrk-allocate memory regions for stacks 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and thread-local storage that we want to consider as live global data. 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Maps from the end address to the start address. 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef map<uintptr_t, uintptr_t, less<uintptr_t>, 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STL_Allocator<pair<const uintptr_t, uintptr_t>, 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapLeakChecker::Allocator> 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) > GlobalRegionCallerRangeMap; 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static GlobalRegionCallerRangeMap* global_region_caller_ranges = NULL; 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(maxim): make our big data structs into own modules 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Disabler is implemented by keeping track of a per-thread count 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of active Disabler objects. Any objects allocated while the 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// count > 0 are not reported. 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_TLS 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static __thread int thread_disable_counter 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The "inital exec" model is faster than the default TLS model, at 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the cost you can't dlopen this library. But dlopen on heap-checker 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// doesn't work anyway -- it must run before main -- so this is a good 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// trade-off. 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# ifdef HAVE___ATTRIBUTE__ 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) __attribute__ ((tls_model ("initial-exec"))) 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# endif 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ; 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline int get_thread_disable_counter() { 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return thread_disable_counter; 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline void set_thread_disable_counter(int value) { 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thread_disable_counter = value; 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else // #ifdef HAVE_TLS 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static pthread_key_t thread_disable_counter_key; 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int main_thread_counter; // storage for use before main() 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool use_main_thread_counter = true; 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(csilvers): this is called from NewHook, in the middle of malloc(). 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If perftools_pthread_getspecific calls malloc, that will lead to an 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// infinite loop. I don't know how to fix that, so I hope it never happens! 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline int get_thread_disable_counter() { 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (use_main_thread_counter) // means we're running really early 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return main_thread_counter; 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* p = perftools_pthread_getspecific(thread_disable_counter_key); 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (intptr_t)p; // kinda evil: store the counter directly in the void* 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline void set_thread_disable_counter(int value) { 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (use_main_thread_counter) { // means we're running really early 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) main_thread_counter = value; 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) intptr_t pointer_sized_value = value; 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // kinda evil: store the counter directly in the void* 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* p = (void*)pointer_sized_value; 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NOTE: this may call malloc, which will call NewHook which will call 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // get_thread_disable_counter() which will call pthread_getspecific(). I 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // don't know if anything bad can happen if we call getspecific() in the 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // middle of a setspecific() call. It seems to work ok in practice... 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) perftools_pthread_setspecific(thread_disable_counter_key, p); 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The idea here is that this initializer will run pretty late: after 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// pthreads have been totally set up. At this point we can call 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// pthreads routines, so we set those up. 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class InitThreadDisableCounter { 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InitThreadDisableCounter() { 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) perftools_pthread_key_create(&thread_disable_counter_key, NULL); 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set up the main thread's value, which we have a special variable for. 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* p = (void*)main_thread_counter; // store the counter directly 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) perftools_pthread_setspecific(thread_disable_counter_key, p); 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) use_main_thread_counter = false; 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)InitThreadDisableCounter init_thread_disable_counter; 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // #ifdef HAVE_TLS 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HeapLeakChecker::Disabler::Disabler() { 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It is faster to unconditionally increment the thread-local 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // counter than to check whether or not heap-checking is on 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in a thread-safe manner. 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int counter = get_thread_disable_counter(); 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set_thread_disable_counter(counter + 1); 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_VLOG(10, "Increasing thread disable counter to %d", counter + 1); 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HeapLeakChecker::Disabler::~Disabler() { 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int counter = get_thread_disable_counter(); 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_DCHECK(counter > 0, ""); 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (counter > 0) { 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set_thread_disable_counter(counter - 1); 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_VLOG(10, "Decreasing thread disable counter to %d", counter); 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_VLOG(0, "Thread disable counter underflow : %d", counter); 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//---------------------------------------------------------------------- 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The size of the largest heap object allocated so far. 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static size_t max_heap_object_size = 0; 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The possible range of addresses that can point 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// into one of the elements of heap_objects. 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static uintptr_t min_heap_address = uintptr_t(-1LL); 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static uintptr_t max_heap_address = 0; 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//---------------------------------------------------------------------- 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Simple casting helpers for uintptr_t and void*: 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<typename T> 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline static const void* AsPtr(T addr) { 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return reinterpret_cast<void*>(addr); 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline static uintptr_t AsInt(const void* ptr) { 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return reinterpret_cast<uintptr_t>(ptr); 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//---------------------------------------------------------------------- 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We've seen reports that strstr causes heap-checker crashes in some 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// libc's (?): 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// http://code.google.com/p/gperftools/issues/detail?id=263 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// It's simple enough to use our own. This is not in time-critical code. 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char* hc_strstr(const char* s1, const char* s2) { 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const size_t len = strlen(s2); 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_CHECK(len > 0, "Unexpected empty string passed to strstr()"); 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (const char* p = strchr(s1, *s2); p != NULL; p = strchr(p+1, *s2)) { 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (strncmp(p, s2, len) == 0) { 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return p; 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//---------------------------------------------------------------------- 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Our hooks for MallocHook 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void NewHook(const void* ptr, size_t size) { 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ptr != NULL) { 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int counter = get_thread_disable_counter(); 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const bool ignore = (counter > 0); 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_VLOG(16, "Recording Alloc: %p of %"PRIuS "; %d", ptr, size, 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int(counter)); 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Fetch the caller's stack trace before acquiring heap_checker_lock. 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* stack[HeapProfileTable::kMaxStackDepth]; 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int depth = HeapProfileTable::GetCallerStackTrace(0, stack); 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { SpinLockHolder l(&heap_checker_lock); 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (size > max_heap_object_size) max_heap_object_size = size; 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uintptr_t addr = AsInt(ptr); 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (addr < min_heap_address) min_heap_address = addr; 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addr += size; 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (addr > max_heap_address) max_heap_address = addr; 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (heap_checker_on) { 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) heap_profile->RecordAlloc(ptr, size, depth, stack); 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ignore) { 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) heap_profile->MarkAsIgnored(ptr); 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_VLOG(17, "Alloc Recorded: %p of %"PRIuS"", ptr, size); 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void DeleteHook(const void* ptr) { 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ptr != NULL) { 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_VLOG(16, "Recording Free %p", ptr); 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { SpinLockHolder l(&heap_checker_lock); 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (heap_checker_on) heap_profile->RecordFree(ptr); 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_VLOG(17, "Free Recorded: %p", ptr); 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//---------------------------------------------------------------------- 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum StackDirection { 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GROWS_TOWARDS_HIGH_ADDRESSES, 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GROWS_TOWARDS_LOW_ADDRESSES, 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UNKNOWN_DIRECTION 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Determine which way the stack grows: 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static StackDirection ATTRIBUTE_NOINLINE GetStackDirection( 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uintptr_t *const ptr) { 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uintptr_t x; 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (&x < ptr) 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GROWS_TOWARDS_LOW_ADDRESSES; 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ptr < &x) 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GROWS_TOWARDS_HIGH_ADDRESSES; 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_CHECK(0, ""); // Couldn't determine the stack direction. 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return UNKNOWN_DIRECTION; 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Direction of stack growth (will initialize via GetStackDirection()) 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static StackDirection stack_direction = UNKNOWN_DIRECTION; 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This routine is called for every thread stack we know about to register it. 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void RegisterStackLocked(const void* top_ptr) { 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_DCHECK(heap_checker_lock.IsHeld(), ""); 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_DCHECK(MemoryRegionMap::LockIsHeld(), ""); 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_VLOG(10, "Thread stack at %p", top_ptr); 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uintptr_t top = AsInt(top_ptr); 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stack_tops->insert(top); // add for later use 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // make sure stack_direction is initialized 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (stack_direction == UNKNOWN_DIRECTION) { 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stack_direction = GetStackDirection(&top); 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Find memory region with this stack 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MemoryRegionMap::Region region; 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (MemoryRegionMap::FindAndMarkStackRegion(top, ®ion)) { 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make the proper portion of the stack live: 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (stack_direction == GROWS_TOWARDS_LOW_ADDRESSES) { 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_VLOG(11, "Live stack at %p of %"PRIuPTR" bytes", 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) top_ptr, region.end_addr - top); 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) live_objects->push_back(AllocObject(top_ptr, region.end_addr - top, 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) THREAD_DATA)); 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { // GROWS_TOWARDS_HIGH_ADDRESSES 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_VLOG(11, "Live stack at %p of %"PRIuPTR" bytes", 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AsPtr(region.start_addr), 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) top - region.start_addr); 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) live_objects->push_back(AllocObject(AsPtr(region.start_addr), 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) top - region.start_addr, 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) THREAD_DATA)); 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // not in MemoryRegionMap, look in library_live_objects: 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (FLAGS_heap_check_ignore_global_live) { 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (LibraryLiveObjectsStacks::iterator lib = library_live_objects->begin(); 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lib != library_live_objects->end(); ++lib) { 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (LiveObjectsStack::iterator span = lib->second.begin(); 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) span != lib->second.end(); ++span) { 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uintptr_t start = AsInt(span->ptr); 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uintptr_t end = start + span->size; 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (start <= top && top < end) { 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_VLOG(11, "Stack at %p is inside /proc/self/maps chunk %p..%p", 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) top_ptr, AsPtr(start), AsPtr(end)); 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Shrink start..end region by chopping away the memory regions in 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // MemoryRegionMap that land in it to undo merging of regions 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in /proc/self/maps, so that we correctly identify what portion 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // of start..end is actually the stack region. 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uintptr_t stack_start = start; 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uintptr_t stack_end = end; 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // can optimize-away this loop, but it does not run often 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_DCHECK(MemoryRegionMap::LockIsHeld(), ""); 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (MemoryRegionMap::RegionIterator r = 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MemoryRegionMap::BeginRegionLocked(); 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) r != MemoryRegionMap::EndRegionLocked(); ++r) { 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (top < r->start_addr && r->start_addr < stack_end) { 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stack_end = r->start_addr; 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (stack_start < r->end_addr && r->end_addr <= top) { 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stack_start = r->end_addr; 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (stack_start != start || stack_end != end) { 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_VLOG(11, "Stack at %p is actually inside memory chunk %p..%p", 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) top_ptr, AsPtr(stack_start), AsPtr(stack_end)); 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make the proper portion of the stack live: 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (stack_direction == GROWS_TOWARDS_LOW_ADDRESSES) { 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_VLOG(11, "Live stack at %p of %"PRIuPTR" bytes", 7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) top_ptr, stack_end - top); 7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) live_objects->push_back( 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AllocObject(top_ptr, stack_end - top, THREAD_DATA)); 7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { // GROWS_TOWARDS_HIGH_ADDRESSES 7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_VLOG(11, "Live stack at %p of %"PRIuPTR" bytes", 7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AsPtr(stack_start), top - stack_start); 7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) live_objects->push_back( 7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AllocObject(AsPtr(stack_start), top - stack_start, THREAD_DATA)); 7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lib->second.erase(span); // kill the rest of the region 7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Put the non-stack part(s) of the region back: 7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (stack_start != start) { 7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lib->second.push_back(AllocObject(AsPtr(start), stack_start - start, 7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MAYBE_LIVE)); 7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (stack_end != end) { 7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lib->second.push_back(AllocObject(AsPtr(stack_end), end - stack_end, 7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MAYBE_LIVE)); 7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_LOG(ERROR, "Memory region for stack at %p not found. " 7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Will likely report false leak positives.", top_ptr); 7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Iterator for heap allocation map data to make ignored objects "live" 7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (i.e., treated as roots for the mark-and-sweep phase) 7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void MakeIgnoredObjectsLiveCallbackLocked( 7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const void* ptr, const HeapProfileTable::AllocInfo& info) { 7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_DCHECK(heap_checker_lock.IsHeld(), ""); 7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (info.ignored) { 7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) live_objects->push_back(AllocObject(ptr, info.object_size, 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MUST_BE_ON_HEAP)); 7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Iterator for heap allocation map data to make objects allocated from 7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// disabled regions of code to be live. 7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void MakeDisabledLiveCallbackLocked( 7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const void* ptr, const HeapProfileTable::AllocInfo& info) { 7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_DCHECK(heap_checker_lock.IsHeld(), ""); 7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool stack_disable = false; 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool range_disable = false; 7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int depth = 0; depth < info.stack_depth; depth++) { 7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uintptr_t addr = AsInt(info.call_stack[depth]); 7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (disabled_ranges) { 7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DisabledRangeMap::const_iterator iter 7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) = disabled_ranges->upper_bound(addr); 7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (iter != disabled_ranges->end()) { 7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_DCHECK(iter->first > addr, ""); 7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (iter->second.start_address < addr && 7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iter->second.max_depth > depth) { 7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) range_disable = true; // in range; dropping 7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (stack_disable || range_disable) { 7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uintptr_t start_address = AsInt(ptr); 7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uintptr_t end_address = start_address + info.object_size; 7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StackTopSet::const_iterator iter 7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) = stack_tops->lower_bound(start_address); 7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (iter != stack_tops->end()) { 7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_DCHECK(*iter >= start_address, ""); 7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*iter < end_address) { 7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We do not disable (treat as live) whole allocated regions 7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // if they are used to hold thread call stacks 7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (i.e. when we find a stack inside). 7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The reason is that we'll treat as live the currently used 7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // stack portions anyway (see RegisterStackLocked), 7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and the rest of the region where the stack lives can well 7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // contain outdated stack variables which are not live anymore, 7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // hence should not be treated as such. 7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_VLOG(11, "Not %s-disabling %"PRIuS" bytes at %p" 7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ": have stack inside: %p", 7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (stack_disable ? "stack" : "range"), 7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info.object_size, ptr, AsPtr(*iter)); 7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_VLOG(11, "%s-disabling %"PRIuS" bytes at %p", 7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (stack_disable ? "Stack" : "Range"), info.object_size, ptr); 7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) live_objects->push_back(AllocObject(ptr, info.object_size, 7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MUST_BE_ON_HEAP)); 7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char kUnnamedProcSelfMapEntry[] = "UNNAMED"; 7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This function takes some fields from a /proc/self/maps line: 7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// start_address start address of a memory region. 7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// end_address end address of a memory region 7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// permissions rwx + private/shared bit 7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// filename filename of the mapped file 7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If the region is not writeable, then it cannot have any heap 8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// pointers in it, otherwise we record it as a candidate live region 8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to get filtered later. 8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void RecordGlobalDataLocked(uintptr_t start_address, 8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uintptr_t end_address, 8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* permissions, 8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* filename) { 8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_DCHECK(heap_checker_lock.IsHeld(), ""); 8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ignore non-writeable regions. 8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (strchr(permissions, 'w') == NULL) return; 8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (filename == NULL || *filename == '\0') { 8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) filename = kUnnamedProcSelfMapEntry; 8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_VLOG(11, "Looking into %s: 0x%" PRIxPTR "..0x%" PRIxPTR, 8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) filename, start_address, end_address); 8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*library_live_objects)[filename]. 8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) push_back(AllocObject(AsPtr(start_address), 8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) end_address - start_address, 8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MAYBE_LIVE)); 8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// See if 'library' from /proc/self/maps has base name 'library_base' 8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// i.e. contains it and has '.' or '-' after it. 8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool IsLibraryNamed(const char* library, const char* library_base) { 8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* p = hc_strstr(library, library_base); 8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t sz = strlen(library_base); 8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return p != NULL && (p[sz] == '.' || p[sz] == '-'); 8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HeapLeakChecker::DisableLibraryAllocsLocked(const char* library, 8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uintptr_t start_address, 8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uintptr_t end_address) { 8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_DCHECK(heap_checker_lock.IsHeld(), ""); 8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int depth = 0; 8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(maxim): maybe this should be extended to also use objdump 8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and pick the text portion of the library more precisely. 8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsLibraryNamed(library, "/libpthread") || 8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // libpthread has a lot of small "system" leaks we don't care about. 8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // In particular it allocates memory to store data supplied via 8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // pthread_setspecific (which can be the only pointer to a heap object). 8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IsLibraryNamed(library, "/libdl") || 8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // library loaders leak some "system" heap that we don't care about 8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IsLibraryNamed(library, "/libcrypto") || 8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Sometimes libcrypto of OpenSSH is compiled with -fomit-frame-pointer 8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (any library can be, of course, but this one often is because speed 8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is so important for making crypto usable). We ignore all its 8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // allocations because we can't see the call stacks. We'd prefer 8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to ignore allocations done in files/symbols that match 8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // "default_malloc_ex|default_realloc_ex" 8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // but that doesn't work when the end-result binary is stripped. 8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IsLibraryNamed(library, "/libjvm") || 8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // JVM has a lot of leaks we don't care about. 8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IsLibraryNamed(library, "/libzip") 8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The JVM leaks java.util.zip.Inflater after loading classes. 8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ) { 8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) depth = 1; // only disable allocation calls directly from the library code 8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (IsLibraryNamed(library, "/ld") 8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // library loader leaks some "system" heap 8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (e.g. thread-local storage) that we don't care about 8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ) { 8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) depth = 2; // disable allocation calls directly from the library code 8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and at depth 2 from it. 8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We need depth 2 here solely because of a libc bug that 8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // forces us to jump through __memalign_hook and MemalignOverride hoops 8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in tcmalloc.cc. 8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Those buggy __libc_memalign() calls are in ld-linux.so and happen for 8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // thread-local storage allocations that we want to ignore here. 8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We go with the depth-2 hack as a workaround for this libc bug: 8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // otherwise we'd need to extend MallocHook interface 8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // so that correct stack depth adjustment can be propagated from 8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the exceptional case of MemalignOverride. 8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Using depth 2 here should not mask real leaks because ld-linux.so 8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // does not call user code. 8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (depth) { 8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_VLOG(10, "Disabling allocations from %s at depth %d:", library, depth); 8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DisableChecksFromToLocked(AsPtr(start_address), AsPtr(end_address), depth); 8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsLibraryNamed(library, "/libpthread") || 8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IsLibraryNamed(library, "/libdl") || 8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IsLibraryNamed(library, "/ld")) { 8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_VLOG(10, "Global memory regions made by %s will be live data", 8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) library); 8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (global_region_caller_ranges == NULL) { 8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) global_region_caller_ranges = 8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new(Allocator::Allocate(sizeof(GlobalRegionCallerRangeMap))) 8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GlobalRegionCallerRangeMap; 8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) global_region_caller_ranges 8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ->insert(make_pair(end_address, start_address)); 8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HeapLeakChecker::ProcMapsResult HeapLeakChecker::UseProcMapsLocked( 8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProcMapsTask proc_maps_task) { 8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_DCHECK(heap_checker_lock.IsHeld(), ""); 8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Need to provide own scratch memory to ProcMapsIterator: 8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProcMapsIterator::Buffer buffer; 9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProcMapsIterator it(0, &buffer); 9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!it.Valid()) { 9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int errsv = errno; 9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_LOG(ERROR, "Could not open /proc/self/maps: errno=%d. " 9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Libraries will not be handled correctly.", errsv); 9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return CANT_OPEN_PROC_MAPS; 9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uint64 start_address, end_address, file_offset; 9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 inode; 9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *permissions, *filename; 9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool saw_shared_lib = false; 9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool saw_nonzero_inode = false; 9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool saw_shared_lib_with_nonzero_inode = false; 9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (it.Next(&start_address, &end_address, &permissions, 9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &file_offset, &inode, &filename)) { 9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (start_address >= end_address) { 9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Warn if a line we can be interested in is ill-formed: 9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (inode != 0) { 9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_LOG(ERROR, "Errors reading /proc/self/maps. " 9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Some global memory regions will not " 9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "be handled correctly."); 9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Silently skip other ill-formed lines: some are possible 9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // probably due to the interplay of how /proc/self/maps is updated 9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // while we read it in chunks in ProcMapsIterator and 9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // do things in this loop. 9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Determine if any shared libraries are present (this is the same 9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // list of extensions as is found in pprof). We want to ignore 9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 'fake' libraries with inode 0 when determining. However, some 9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // systems don't share inodes via /proc, so we turn off this check 9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // if we don't see any evidence that we're getting inode info. 9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (inode != 0) { 9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) saw_nonzero_inode = true; 9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((hc_strstr(filename, "lib") && hc_strstr(filename, ".so")) || 9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hc_strstr(filename, ".dll") || 9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // not all .dylib filenames start with lib. .dylib is big enough 9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that we are unlikely to get false matches just checking that. 9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hc_strstr(filename, ".dylib") || hc_strstr(filename, ".bundle")) { 9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) saw_shared_lib = true; 9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (inode != 0) { 9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) saw_shared_lib_with_nonzero_inode = true; 9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (proc_maps_task) { 9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case DISABLE_LIBRARY_ALLOCS: 9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // All lines starting like 9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // "401dc000-4030f000 r??p 00132000 03:01 13991972 lib/bin" 9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // identify a data and code sections of a shared library or our binary 9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (inode != 0 && strncmp(permissions, "r-xp", 4) == 0) { 9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DisableLibraryAllocsLocked(filename, start_address, end_address); 9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case RECORD_GLOBAL_DATA: 9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RecordGlobalDataLocked(start_address, end_address, 9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) permissions, filename); 9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_CHECK(0, ""); 9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If /proc/self/maps is reporting inodes properly (we saw a 9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // non-zero inode), then we only say we saw a shared lib if we saw a 9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 'real' one, with a non-zero inode. 9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (saw_nonzero_inode) { 9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) saw_shared_lib = saw_shared_lib_with_nonzero_inode; 9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!saw_shared_lib) { 9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_LOG(ERROR, "No shared libs detected. Will likely report false leak " 9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "positives for statically linked executables."); 9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NO_SHARED_LIBS_IN_PROC_MAPS; 9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return PROC_MAPS_USED; 9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Total number and size of live objects dropped from the profile; 9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (re)initialized in IgnoreAllLiveObjectsLocked. 9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int64 live_objects_total; 9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int64 live_bytes_total; 9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// pid of the thread that is doing the current leak check 9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (protected by our lock; IgnoreAllLiveObjectsLocked sets it) 9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static pid_t self_thread_pid = 0; 9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Status of our thread listing callback execution 9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (protected by our lock; used from within IgnoreAllLiveObjectsLocked) 9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static enum { 9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CALLBACK_NOT_STARTED, 9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CALLBACK_STARTED, 9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CALLBACK_COMPLETED, 9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} thread_listing_status = CALLBACK_NOT_STARTED; 9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Ideally to avoid deadlocks this function should not result in any libc 9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// or other function calls that might need to lock a mutex: 9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// It is called when all threads of a process are stopped 9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// at arbitrary points thus potentially holding those locks. 9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// In practice we are calling some simple i/o and sprintf-type library functions 10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// for logging messages, but use only our own LowLevelAlloc::Arena allocator. 10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This is known to be buggy: the library i/o function calls are able to cause 10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// deadlocks when they request a lock that a stopped thread happens to hold. 10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This issue as far as we know have so far not resulted in any deadlocks 10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in practice, so for now we are taking our chance that the deadlocks 10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// have insignificant frequency. 10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If such deadlocks become a problem we should make the i/o calls 10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// into appropriately direct system calls (or eliminate them), 10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in particular write() is not safe and vsnprintf() is potentially dangerous 10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// due to reliance on locale functions (these are called through RAW_LOG 10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and in other ways). 10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*static*/ int HeapLeakChecker::IgnoreLiveThreadsLocked(void* parameter, 10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int num_threads, 10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pid_t* thread_pids, 10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) va_list /*ap*/) { 10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_DCHECK(heap_checker_lock.IsHeld(), ""); 10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thread_listing_status = CALLBACK_STARTED; 10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_VLOG(11, "Found %d threads (from pid %d)", num_threads, getpid()); 10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FLAGS_heap_check_ignore_global_live) { 10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UseProcMapsLocked(RECORD_GLOBAL_DATA); 10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We put the registers from other threads here 10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to make pointers stored in them live. 10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) vector<void*, STL_Allocator<void*, Allocator> > thread_registers; 10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int failures = 0; 10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < num_threads; ++i) { 10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the leak checking thread itself is handled 10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // specially via self_thread_stack, not here: 10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (thread_pids[i] == self_thread_pid) continue; 10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_VLOG(11, "Handling thread with pid %d", thread_pids[i]); 10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if (defined(__i386__) || defined(__x86_64)) && \ 10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) defined(HAVE_LINUX_PTRACE_H) && defined(HAVE_SYS_SYSCALL_H) && defined(DUMPER) 10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i386_regs thread_regs; 10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define sys_ptrace(r, p, a, d) syscall(SYS_ptrace, (r), (p), (a), (d)) 10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We use sys_ptrace to avoid thread locking 10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // because this is called from ListAllProcessThreads 10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // when all but this thread are suspended. 10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sys_ptrace(PTRACE_GETREGS, thread_pids[i], NULL, &thread_regs) == 0) { 10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Need to use SP to get all the data from the very last stack frame: 10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) COMPILE_ASSERT(sizeof(thread_regs.SP) == sizeof(void*), 10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SP_register_does_not_look_like_a_pointer); 10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RegisterStackLocked(reinterpret_cast<void*>(thread_regs.SP)); 10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make registers live (just in case PTRACE_ATTACH resulted in some 10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // register pointers still being in the registers and not on the stack): 10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (void** p = reinterpret_cast<void**>(&thread_regs); 10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p < reinterpret_cast<void**>(&thread_regs + 1); ++p) { 10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_VLOG(12, "Thread register %p", *p); 10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thread_registers.push_back(*p); 10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) failures += 1; 10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) failures += 1; 10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Use all the collected thread (stack) liveness sources: 10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IgnoreLiveObjectsLocked("threads stack data", ""); 10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (thread_registers.size()) { 10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make thread registers be live heap data sources. 10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we rely here on the fact that vector is in one memory chunk: 10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_VLOG(11, "Live registers at %p of %"PRIuS" bytes", 10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &thread_registers[0], thread_registers.size() * sizeof(void*)); 10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) live_objects->push_back(AllocObject(&thread_registers[0], 10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thread_registers.size() * sizeof(void*), 10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) THREAD_REGISTERS)); 10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IgnoreLiveObjectsLocked("threads register data", ""); 10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Do all other liveness walking while all threads are stopped: 10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IgnoreNonThreadLiveObjectsLocked(); 10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Can now resume the threads: 10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResumeAllProcessThreads(num_threads, thread_pids); 10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thread_listing_status = CALLBACK_COMPLETED; 10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return failures; 10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Stack top of the thread that is doing the current leak check 10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (protected by our lock; IgnoreAllLiveObjectsLocked sets it) 10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const void* self_thread_stack_top; 10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HeapLeakChecker::IgnoreNonThreadLiveObjectsLocked() { 10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_DCHECK(heap_checker_lock.IsHeld(), ""); 10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_DCHECK(MemoryRegionMap::LockIsHeld(), ""); 10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_VLOG(11, "Handling self thread with pid %d", self_thread_pid); 10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Register our own stack: 10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Important that all stack ranges (including the one here) 10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // are known before we start looking at them 10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in MakeDisabledLiveCallbackLocked: 10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RegisterStackLocked(self_thread_stack_top); 10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IgnoreLiveObjectsLocked("stack data", ""); 10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make objects we were told to ignore live: 11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ignored_objects) { 11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (IgnoredObjectsMap::const_iterator object = ignored_objects->begin(); 11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) object != ignored_objects->end(); ++object) { 11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const void* ptr = AsPtr(object->first); 11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_VLOG(11, "Ignored live object at %p of %"PRIuS" bytes", 11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ptr, object->second); 11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) live_objects-> 11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) push_back(AllocObject(ptr, object->second, MUST_BE_ON_HEAP)); 11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we do this liveness check for ignored_objects before doing any 11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // live heap walking to make sure it does not fail needlessly: 11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t object_size; 11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!(heap_profile->FindAlloc(ptr, &object_size) && 11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) object->second == object_size)) { 11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_LOG(FATAL, "Object at %p of %"PRIuS" bytes from an" 11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) " IgnoreObject() has disappeared", ptr, object->second); 11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IgnoreLiveObjectsLocked("ignored objects", ""); 11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Treat objects that were allocated when a Disabler was live as 11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // roots. I.e., if X was allocated while a Disabler was active, 11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and Y is reachable from X, arrange that neither X nor Y are 11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // treated as leaks. 11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) heap_profile->IterateAllocs(MakeIgnoredObjectsLiveCallbackLocked); 11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IgnoreLiveObjectsLocked("disabled objects", ""); 11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make code-address-disabled objects live and ignored: 11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This in particular makes all thread-specific data live 11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // because the basic data structure to hold pointers to thread-specific data 11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is allocated from libpthreads and we have range-disabled that 11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // library code with UseProcMapsLocked(DISABLE_LIBRARY_ALLOCS); 11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // so now we declare all thread-specific data reachable from there as live. 11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) heap_profile->IterateAllocs(MakeDisabledLiveCallbackLocked); 11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IgnoreLiveObjectsLocked("disabled code", ""); 11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Actually make global data live: 11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FLAGS_heap_check_ignore_global_live) { 11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool have_null_region_callers = false; 11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (LibraryLiveObjectsStacks::iterator l = library_live_objects->begin(); 11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) l != library_live_objects->end(); ++l) { 11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_CHECK(live_objects->empty(), ""); 11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Process library_live_objects in l->second 11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // filtering them by MemoryRegionMap: 11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It's safe to iterate over MemoryRegionMap 11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // w/o locks here as we are inside MemoryRegionMap::Lock(): 11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_DCHECK(MemoryRegionMap::LockIsHeld(), ""); 11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The only change to MemoryRegionMap possible in this loop 11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is region addition as a result of allocating more memory 11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // for live_objects. This won't invalidate the RegionIterator 11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // or the intent of the loop. 11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // --see the comment by MemoryRegionMap::BeginRegionLocked(). 11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (MemoryRegionMap::RegionIterator region = 11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MemoryRegionMap::BeginRegionLocked(); 11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) region != MemoryRegionMap::EndRegionLocked(); ++region) { 11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // "region" from MemoryRegionMap is to be subtracted from 11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (tentatively live) regions in l->second 11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // if it has a stack inside or it was allocated by 11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a non-special caller (not one covered by a range 11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in global_region_caller_ranges). 11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This will in particular exclude all memory chunks used 11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // by the heap itself as well as what's been allocated with 11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // any allocator on top of mmap. 11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool subtract = true; 11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!region->is_stack && global_region_caller_ranges) { 11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (region->caller() == static_cast<uintptr_t>(NULL)) { 11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) have_null_region_callers = true; 11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GlobalRegionCallerRangeMap::const_iterator iter 11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) = global_region_caller_ranges->upper_bound(region->caller()); 11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (iter != global_region_caller_ranges->end()) { 11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_DCHECK(iter->first > region->caller(), ""); 11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (iter->second < region->caller()) { // in special region 11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subtract = false; 11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (subtract) { 11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The loop puts the result of filtering l->second into live_objects: 11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (LiveObjectsStack::const_iterator i = l->second.begin(); 11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != l->second.end(); ++i) { 11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // subtract *region from *i 11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uintptr_t start = AsInt(i->ptr); 11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uintptr_t end = start + i->size; 11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (region->start_addr <= start && end <= region->end_addr) { 11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // full deletion due to subsumption 11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (start < region->start_addr && 11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) region->end_addr < end) { // cutting-out split 11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) live_objects->push_back(AllocObject(i->ptr, 11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) region->start_addr - start, 11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IN_GLOBAL_DATA)); 11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) live_objects->push_back(AllocObject(AsPtr(region->end_addr), 11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) end - region->end_addr, 11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IN_GLOBAL_DATA)); 11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (region->end_addr > start && 11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) region->start_addr <= start) { // cut from start 11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) live_objects->push_back(AllocObject(AsPtr(region->end_addr), 11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) end - region->end_addr, 12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IN_GLOBAL_DATA)); 12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (region->start_addr > start && 12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) region->start_addr < end) { // cut from end 12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) live_objects->push_back(AllocObject(i->ptr, 12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) region->start_addr - start, 12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IN_GLOBAL_DATA)); 12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { // pass: no intersection 12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) live_objects->push_back(AllocObject(i->ptr, i->size, 12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IN_GLOBAL_DATA)); 12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Move live_objects back into l->second 12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // for filtering by the next region. 12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) live_objects->swap(l->second); 12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) live_objects->clear(); 12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now get and use live_objects from the final version of l->second: 12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (VLOG_IS_ON(11)) { 12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (LiveObjectsStack::const_iterator i = l->second.begin(); 12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != l->second.end(); ++i) { 12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_VLOG(11, "Library live region at %p of %"PRIuPTR" bytes", 12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i->ptr, i->size); 12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) live_objects->swap(l->second); 12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IgnoreLiveObjectsLocked("in globals of\n ", l->first.c_str()); 12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (have_null_region_callers) { 12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_LOG(ERROR, "Have memory regions w/o callers: " 12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "might report false leaks"); 12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Allocator::DeleteAndNull(&library_live_objects); 12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Callback for ListAllProcessThreads in IgnoreAllLiveObjectsLocked below 12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to test/verify that we have just the one main thread, in which case 12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// we can do everything in that main thread, 12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// so that CPU profiler can collect all its samples. 12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns the number of threads in the process. 12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int IsOneThread(void* parameter, int num_threads, 12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pid_t* thread_pids, va_list ap) { 12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (num_threads != 1) { 12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_LOG(WARNING, "Have threads: Won't CPU-profile the bulk of leak " 12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "checking work happening in IgnoreLiveThreadsLocked!"); 12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResumeAllProcessThreads(num_threads, thread_pids); 12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return num_threads; 12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Dummy for IgnoreAllLiveObjectsLocked below. 12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Making it global helps with compiler warnings. 12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static va_list dummy_ap; 12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HeapLeakChecker::IgnoreAllLiveObjectsLocked(const void* self_stack_top) { 12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_DCHECK(heap_checker_lock.IsHeld(), ""); 12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_CHECK(live_objects == NULL, ""); 12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) live_objects = new(Allocator::Allocate(sizeof(LiveObjectsStack))) 12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LiveObjectsStack; 12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stack_tops = new(Allocator::Allocate(sizeof(StackTopSet))) StackTopSet; 12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // reset the counts 12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) live_objects_total = 0; 12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) live_bytes_total = 0; 12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Reduce max_heap_object_size to FLAGS_heap_check_max_pointer_offset 12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // for the time of leak check. 12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // FLAGS_heap_check_max_pointer_offset caps max_heap_object_size 12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to manage reasonably low chances of random bytes 12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // appearing to be pointing into large actually leaked heap objects. 12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const size_t old_max_heap_object_size = max_heap_object_size; 12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) max_heap_object_size = ( 12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FLAGS_heap_check_max_pointer_offset != -1 12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ? min(size_t(FLAGS_heap_check_max_pointer_offset), max_heap_object_size) 12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : max_heap_object_size); 12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Record global data as live: 12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FLAGS_heap_check_ignore_global_live) { 12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) library_live_objects = 12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new(Allocator::Allocate(sizeof(LibraryLiveObjectsStacks))) 12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LibraryLiveObjectsStacks; 12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ignore all thread stacks: 12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) thread_listing_status = CALLBACK_NOT_STARTED; 12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool need_to_ignore_non_thread_objects = true; 12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self_thread_pid = getpid(); 12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self_thread_stack_top = self_stack_top; 12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FLAGS_heap_check_ignore_thread_live) { 12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // In case we are doing CPU profiling we'd like to do all the work 12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in the main thread, not in the special thread created by 12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ListAllProcessThreads, so that CPU profiler can collect all its samples. 12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The machinery of ListAllProcessThreads conflicts with the CPU profiler 12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // by also relying on signals and ::sigaction. 12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We can do this (run everything in the main thread) safely 12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // only if there's just the main thread itself in our process. 12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This variable reflects these two conditions: 12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool want_and_can_run_in_main_thread = 12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProfilingIsEnabledForAllThreads() && 12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ListAllProcessThreads(NULL, IsOneThread) == 1; 12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // When the normal path of ListAllProcessThreads below is taken, 12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we fully suspend the threads right here before any liveness checking 13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and keep them suspended for the whole time of liveness checking 13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // inside of the IgnoreLiveThreadsLocked callback. 13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (The threads can't (de)allocate due to lock on the delete hook but 13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // if not suspended they could still mess with the pointer 13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // graph while we walk it). 13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int r = want_and_can_run_in_main_thread 13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ? IgnoreLiveThreadsLocked(NULL, 1, &self_thread_pid, dummy_ap) 13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : ListAllProcessThreads(NULL, IgnoreLiveThreadsLocked); 13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) need_to_ignore_non_thread_objects = r < 0; 13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (r < 0) { 13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_LOG(WARNING, "Thread finding failed with %d errno=%d", r, errno); 13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (thread_listing_status == CALLBACK_COMPLETED) { 13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_LOG(INFO, "Thread finding callback " 13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "finished ok; hopefully everything is fine"); 13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) need_to_ignore_non_thread_objects = false; 13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (thread_listing_status == CALLBACK_STARTED) { 13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_LOG(FATAL, "Thread finding callback was " 13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "interrupted or crashed; can't fix this"); 13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { // CALLBACK_NOT_STARTED 13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_LOG(ERROR, "Could not find thread stacks. " 13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Will likely report false leak positives."); 13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (r != 0) { 13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_LOG(ERROR, "Thread stacks not found for %d threads. " 13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Will likely report false leak positives.", r); 13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_VLOG(11, "Thread stacks appear to be found for all threads"); 13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_LOG(WARNING, "Not looking for thread stacks; " 13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "objects reachable only from there " 13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "will be reported as leaks"); 13325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Do all other live data ignoring here if we did not do it 13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // within thread listing callback with all threads stopped. 13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (need_to_ignore_non_thread_objects) { 13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FLAGS_heap_check_ignore_global_live) { 13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UseProcMapsLocked(RECORD_GLOBAL_DATA); 13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IgnoreNonThreadLiveObjectsLocked(); 13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (live_objects_total) { 13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_VLOG(10, "Ignoring %"PRId64" reachable objects of %"PRId64" bytes", 13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) live_objects_total, live_bytes_total); 13445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Free these: we made them here and heap_profile never saw them 13465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Allocator::DeleteAndNull(&live_objects); 13475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Allocator::DeleteAndNull(&stack_tops); 13485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) max_heap_object_size = old_max_heap_object_size; // reset this var 13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Alignment at which we should consider pointer positions 13525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in IgnoreLiveObjectsLocked. Will normally use the value of 13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// FLAGS_heap_check_pointer_source_alignment. 13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static size_t pointer_source_alignment = kPointerSourceAlignment; 13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Global lock for HeapLeakChecker::DoNoLeaks 13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to protect pointer_source_alignment. 13575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static SpinLock alignment_checker_lock(SpinLock::LINKER_INITIALIZED); 13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This function changes the live bits in the heap_profile-table's state: 13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// we only record the live objects to be skipped. 13615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 13625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// When checking if a byte sequence points to a heap object we use 13635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// HeapProfileTable::FindInsideAlloc to handle both pointers to 13645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the start and inside of heap-allocated objects. 13655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The "inside" case needs to be checked to support 13665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// at least the following relatively common cases: 13675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - C++ arrays allocated with new FooClass[size] for classes 13685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// with destructors have their size recorded in a sizeof(int) field 13695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// before the place normal pointers point to. 13705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - basic_string<>-s for e.g. the C++ library of gcc 3.4 13715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// have the meta-info in basic_string<...>::_Rep recorded 13725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// before the place normal pointers point to. 13735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - Multiple-inherited objects have their pointers when cast to 13745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// different base classes pointing inside of the actually 13755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// allocated object. 13765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - Sometimes reachability pointers point to member objects of heap objects, 13775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and then those member objects point to the full heap object. 13785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - Third party UnicodeString: it stores a 32-bit refcount 13795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (in both 32-bit and 64-bit binaries) as the first uint32 13805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in the allocated memory and a normal pointer points at 13815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the second uint32 behind the refcount. 13825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// By finding these additional objects here 13835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// we slightly increase the chance to mistake random memory bytes 13845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// for a pointer and miss a leak in a particular run of a binary. 13855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 13865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*static*/ void HeapLeakChecker::IgnoreLiveObjectsLocked(const char* name, 13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* name2) { 13885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_DCHECK(heap_checker_lock.IsHeld(), ""); 13895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 live_object_count = 0; 13905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 live_byte_count = 0; 13915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (!live_objects->empty()) { 13925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* object = 13935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<const char*>(live_objects->back().ptr); 13945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t size = live_objects->back().size; 13955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ObjectPlacement place = live_objects->back().place; 13965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) live_objects->pop_back(); 13975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (place == MUST_BE_ON_HEAP && heap_profile->MarkAsLive(object)) { 13985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) live_object_count += 1; 13995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) live_byte_count += size; 14005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_VLOG(13, "Looking for heap pointers in %p of %"PRIuS" bytes", 14025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) object, size); 14035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* const whole_object = object; 14045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t const whole_size = size; 14055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Try interpretting any byte sequence in object,size as a heap pointer: 14065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const size_t remainder = AsInt(object) % pointer_source_alignment; 14075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (remainder) { 14085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) object += pointer_source_alignment - remainder; 14095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (size >= pointer_source_alignment - remainder) { 14105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size -= pointer_source_alignment - remainder; 14115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 14125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size = 0; 14135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (size < sizeof(void*)) continue; 14165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef NO_FRAME_POINTER 14185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Frame pointer omission requires us to use libunwind, which uses direct 14195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // mmap and munmap system calls, and that needs special handling. 14205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (name2 == kUnnamedProcSelfMapEntry) { 14215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const uintptr_t page_mask = ~(getpagesize() - 1); 14225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uintptr_t addr = reinterpret_cast<uintptr_t>(object); 14235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((addr & page_mask) == 0 && (size & page_mask) == 0) { 14245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is an object we slurped from /proc/self/maps. 14255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It may or may not be readable at this point. 14265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 14275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // In case all the above conditions made a mistake, and the object is 14285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // not related to libunwind, we also verify that it's not readable 14295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // before ignoring it. 14305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (msync(const_cast<char*>(object), size, MS_ASYNC) != 0) { 14315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Skip unreadable object, so we don't crash trying to sweep it. 14325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_VLOG(0, "Ignoring inaccessible object [%p, %p) " 14335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "(msync error %d (%s))", 14345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) object, object + size, errno, strerror(errno)); 14355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 14365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 14405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* const max_object = object + size - sizeof(void*); 14425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (object <= max_object) { 14435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // potentially unaligned load: 14445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uintptr_t addr = *reinterpret_cast<const uintptr_t*>(object); 14455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Do fast check before the more expensive HaveOnHeapLocked lookup: 14465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // this code runs for all memory words that are potentially pointers: 14475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const bool can_be_on_heap = 14485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Order tests by the likelyhood of the test failing in 64/32 bit modes. 14495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Yes, this matters: we either lose 5..6% speed in 32 bit mode 14505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (which is already slower) or by a factor of 1.5..1.91 in 64 bit mode. 14515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // After the alignment test got dropped the above performance figures 14525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // must have changed; might need to revisit this. 14535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(__x86_64__) 14545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addr <= max_heap_address && // <= is for 0-sized object with max addr 14555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) min_heap_address <= addr; 14565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 14575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) min_heap_address <= addr && 14585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) addr <= max_heap_address; // <= is for 0-sized object with max addr 14595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 14605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (can_be_on_heap) { 14615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const void* ptr = reinterpret_cast<const void*>(addr); 14625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Too expensive (inner loop): manually uncomment when debugging: 14635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // RAW_VLOG(17, "Trying pointer to %p at %p", ptr, object); 14645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t object_size; 14655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (HaveOnHeapLocked(&ptr, &object_size) && 14665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) heap_profile->MarkAsLive(ptr)) { 14675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We take the (hopefully low) risk here of encountering by accident 14685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a byte sequence in memory that matches an address of 14695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a heap object which is in fact leaked. 14705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // I.e. in very rare and probably not repeatable/lasting cases 14715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we might miss some real heap memory leaks. 14725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_VLOG(14, "Found pointer to %p of %"PRIuS" bytes at %p " 14735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "inside %p of size %"PRIuS"", 14745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ptr, object_size, object, whole_object, whole_size); 14755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (VLOG_IS_ON(15)) { 14765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // log call stacks to help debug how come something is not a leak 14775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapProfileTable::AllocInfo alloc; 14785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool r = heap_profile->FindAllocDetails(ptr, &alloc); 14795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) r = r; // suppress compiler warning in non-debug mode 14805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_DCHECK(r, ""); // sanity 14815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_LOG(INFO, "New live %p object's alloc stack:", ptr); 14825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < alloc.stack_depth; ++i) { 14835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_LOG(INFO, " @ %p", alloc.call_stack[i]); 14845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) live_object_count += 1; 14875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) live_byte_count += object_size; 14885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) live_objects->push_back(AllocObject(ptr, object_size, 14895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IGNORED_ON_HEAP)); 14905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) object += pointer_source_alignment; 14935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) live_objects_total += live_object_count; 14965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) live_bytes_total += live_byte_count; 14975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (live_object_count) { 14985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_VLOG(10, "Removed %"PRId64" live heap objects of %"PRId64" bytes: %s%s", 14995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) live_object_count, live_byte_count, name, name2); 15005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//---------------------------------------------------------------------- 15045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// HeapLeakChecker leak check disabling components 15055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//---------------------------------------------------------------------- 15065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 15085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HeapLeakChecker::DisableChecksIn(const char* pattern) { 15095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_LOG(WARNING, "DisableChecksIn(%s) is ignored", pattern); 15105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 15135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HeapLeakChecker::DoIgnoreObject(const void* ptr) { 15145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpinLockHolder l(&heap_checker_lock); 15155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!heap_checker_on) return; 15165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t object_size; 15175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!HaveOnHeapLocked(&ptr, &object_size)) { 15185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_LOG(ERROR, "No live heap object at %p to ignore", ptr); 15195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 15205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_VLOG(10, "Going to ignore live object at %p of %"PRIuS" bytes", 15215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ptr, object_size); 15225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ignored_objects == NULL) { 15235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ignored_objects = new(Allocator::Allocate(sizeof(IgnoredObjectsMap))) 15245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IgnoredObjectsMap; 15255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ignored_objects->insert(make_pair(AsInt(ptr), object_size)).second) { 15275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_LOG(WARNING, "Object at %p is already being ignored", ptr); 15285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 15335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HeapLeakChecker::UnIgnoreObject(const void* ptr) { 15345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpinLockHolder l(&heap_checker_lock); 15355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!heap_checker_on) return; 15365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t object_size; 15375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!HaveOnHeapLocked(&ptr, &object_size)) { 15385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_LOG(FATAL, "No live heap object at %p to un-ignore", ptr); 15395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 15405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool found = false; 15415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ignored_objects) { 15425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IgnoredObjectsMap::iterator object = ignored_objects->find(AsInt(ptr)); 15435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (object != ignored_objects->end() && object_size == object->second) { 15445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ignored_objects->erase(object); 15455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) found = true; 15465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_VLOG(10, "Now not going to ignore live object " 15475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "at %p of %"PRIuS" bytes", ptr, object_size); 15485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!found) RAW_LOG(FATAL, "Object at %p has not been ignored", ptr); 15515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//---------------------------------------------------------------------- 15555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// HeapLeakChecker non-static functions 15565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//---------------------------------------------------------------------- 15575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)char* HeapLeakChecker::MakeProfileNameLocked() { 15595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_DCHECK(lock_->IsHeld(), ""); 15605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_DCHECK(heap_checker_lock.IsHeld(), ""); 15615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int len = profile_name_prefix->size() + strlen(name_) + 5 + 15625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) strlen(HeapProfileTable::kFileExt) + 1; 15635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char* file_name = reinterpret_cast<char*>(Allocator::Allocate(len)); 15645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) snprintf(file_name, len, "%s.%s-end%s", 15655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_name_prefix->c_str(), name_, 15665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapProfileTable::kFileExt); 15675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return file_name; 15685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HeapLeakChecker::Create(const char *name, bool make_start_snapshot) { 15715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpinLockHolder l(lock_); 15725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name_ = NULL; // checker is inactive 15735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) start_snapshot_ = NULL; 15745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) has_checked_ = false; 15755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inuse_bytes_increase_ = 0; 15765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inuse_allocs_increase_ = 0; 15775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) keep_profiles_ = false; 15785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char* n = new char[strlen(name) + 1]; // do this before we lock 15795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IgnoreObject(n); // otherwise it might be treated as live due to our stack 15805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { // Heap activity in other threads is paused for this whole scope. 15815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpinLockHolder al(&alignment_checker_lock); 15825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpinLockHolder hl(&heap_checker_lock); 15835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MemoryRegionMap::LockHolder ml; 15845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (heap_checker_on && profile_name_prefix != NULL) { 15855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_DCHECK(strchr(name, '/') == NULL, "must be a simple name"); 15865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcpy(n, name, strlen(name) + 1); 15875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name_ = n; // checker is active 15885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (make_start_snapshot) { 15895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) start_snapshot_ = heap_profile->TakeSnapshot(); 15905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const HeapProfileTable::Stats& t = heap_profile->total(); 15935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const size_t start_inuse_bytes = t.alloc_size - t.free_size; 15945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const size_t start_inuse_allocs = t.allocs - t.frees; 15955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_VLOG(10, "Start check \"%s\" profile: %"PRIuS" bytes " 15965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "in %"PRIuS" objects", 15975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name_, start_inuse_bytes, start_inuse_allocs); 15985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 15995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_LOG(WARNING, "Heap checker is not active, " 16005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "hence checker \"%s\" will do nothing!", name); 16015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_LOG(WARNING, "To activate set the HEAPCHECK environment variable.\n"); 16025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (name_ == NULL) { 16055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UnIgnoreObject(n); 16065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete[] n; // must be done after we unlock 16075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HeapLeakChecker::HeapLeakChecker(const char *name) : lock_(new SpinLock) { 16115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_DCHECK(strcmp(name, "_main_") != 0, "_main_ is reserved"); 16125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Create(name, true/*create start_snapshot_*/); 16135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HeapLeakChecker::HeapLeakChecker() : lock_(new SpinLock) { 16165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FLAGS_heap_check_before_constructors) { 16175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We want to check for leaks of objects allocated during global 16185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // constructors (i.e., objects allocated already). So we do not 16195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // create a baseline snapshot and hence check for leaks of objects 16205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that may have already been created. 16215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Create("_main_", false); 16225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 16235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We want to ignore leaks of objects allocated during global 16245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // constructors (i.e., objects allocated already). So we snapshot 16255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the current heap contents and use them as a baseline that is 16265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // not reported by the leak checker. 16275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Create("_main_", true); 16285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ssize_t HeapLeakChecker::BytesLeaked() const { 16325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpinLockHolder l(lock_); 16335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!has_checked_) { 16345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_LOG(FATAL, "*NoLeaks|SameHeap must execute before this call"); 16355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return inuse_bytes_increase_; 16375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ssize_t HeapLeakChecker::ObjectsLeaked() const { 16405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpinLockHolder l(lock_); 16415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!has_checked_) { 16425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_LOG(FATAL, "*NoLeaks|SameHeap must execute before this call"); 16435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return inuse_allocs_increase_; 16455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Save pid of main thread for using in naming dump files 16485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int32 main_thread_pid = getpid(); 16495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_PROGRAM_INVOCATION_NAME 16505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern char* program_invocation_name; 16515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern char* program_invocation_short_name; 16525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char* invocation_name() { return program_invocation_short_name; } 16535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static string invocation_path() { return program_invocation_name; } 16545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 16555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char* invocation_name() { return "<your binary>"; } 16565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static string invocation_path() { return "<your binary>"; } 16575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 16585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Prints commands that users can run to get more information 16605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// about the reported leaks. 16615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void SuggestPprofCommand(const char* pprof_file_arg) { 16625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Extra help information to print for the user when the test is 16635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // being run in a way where the straightforward pprof command will 16645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // not suffice. 16655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string extra_help; 16665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Common header info to print for remote runs 16685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const string remote_header = 16695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "This program is being executed remotely and therefore the pprof\n" 16705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "command printed above will not work. Either run this program\n" 16715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "locally, or adjust the pprof command as follows to allow it to\n" 16725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "work on your local machine:\n"; 16735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Extra command for fetching remote data 16755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string fetch_cmd; 16765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_LOG(WARNING, 16785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "\n\n" 16795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "If the preceding stack traces are not enough to find " 16805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "the leaks, try running THIS shell command:\n\n" 16815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "%s%s %s \"%s\" --inuse_objects --lines --heapcheck " 16825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) " --edgefraction=1e-10 --nodefraction=1e-10 --gv\n" 16835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "\n" 16845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "%s" 16855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "If you are still puzzled about why the leaks are " 16865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "there, try rerunning this program with " 16875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "HEAP_CHECK_TEST_POINTER_ALIGNMENT=1 and/or with " 16885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "HEAP_CHECK_MAX_POINTER_OFFSET=-1\n" 16895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "If the leak report occurs in a small fraction of runs, " 16905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "try running with TCMALLOC_MAX_FREE_QUEUE_SIZE of few hundred MB " 16915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "or with TCMALLOC_RECLAIM_MEMORY=false, " // only works for debugalloc 16925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "it might help find leaks more repeatably\n", 16935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fetch_cmd.c_str(), 16945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "pprof", // works as long as pprof is on your path 16955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) invocation_path().c_str(), 16965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pprof_file_arg, 16975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extra_help.c_str() 16985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ); 16995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 17005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HeapLeakChecker::DoNoLeaks(ShouldSymbolize should_symbolize) { 17025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpinLockHolder l(lock_); 17035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The locking also helps us keep the messages 17045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // for the two checks close together. 17055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpinLockHolder al(&alignment_checker_lock); 17065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // thread-safe: protected by alignment_checker_lock 17085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool have_disabled_hooks_for_symbolize = false; 17095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Once we've checked for leaks and symbolized the results once, it's 17105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // not safe to do it again. This is because in order to symbolize 17115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // safely, we had to disable all the malloc hooks here, so we no 17125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // longer can be confident we've collected all the data we need. 17135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (have_disabled_hooks_for_symbolize) { 17145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_LOG(FATAL, "Must not call heap leak checker manually after " 17155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) " program-exit's automatic check."); 17165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapProfileTable::Snapshot* leaks = NULL; 17195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char* pprof_file = NULL; 17205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 17225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Heap activity in other threads is paused during this function 17235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (i.e. until we got all profile difference info). 17245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpinLockHolder hl(&heap_checker_lock); 17255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (heap_checker_on == false) { 17265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (name_ != NULL) { // leak checking enabled when created the checker 17275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_LOG(WARNING, "Heap leak checker got turned off after checker " 17285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "\"%s\" has been created, no leak check is being done for it!", 17295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name_); 17305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 17325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update global_region_caller_ranges. They may need to change since 17355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // e.g. initialization because shared libraries might have been loaded or 17365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // unloaded. 17375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Allocator::DeleteAndNullIfNot(&global_region_caller_ranges); 17385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProcMapsResult pm_result = UseProcMapsLocked(DISABLE_LIBRARY_ALLOCS); 17395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_CHECK(pm_result == PROC_MAPS_USED, ""); 17405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Keep track of number of internally allocated objects so we 17425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // can detect leaks in the heap-leak-checket itself 17435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int initial_allocs = Allocator::alloc_count(); 17445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (name_ == NULL) { 17465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_LOG(FATAL, "Heap leak checker must not be turned on " 17475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "after construction of a HeapLeakChecker"); 17485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MemoryRegionMap::LockHolder ml; 17515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int a_local_var; // Use our stack ptr to make stack data live: 17525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make the heap profile, other threads are locked out. 17545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapProfileTable::Snapshot* base = 17555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<HeapProfileTable::Snapshot*>(start_snapshot_); 17565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_DCHECK(FLAGS_heap_check_pointer_source_alignment > 0, ""); 17575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pointer_source_alignment = FLAGS_heap_check_pointer_source_alignment; 17585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IgnoreAllLiveObjectsLocked(&a_local_var); 17595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) leaks = heap_profile->NonLiveSnapshot(base); 17605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inuse_bytes_increase_ = static_cast<ssize_t>(leaks->total().alloc_size); 17625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inuse_allocs_increase_ = static_cast<ssize_t>(leaks->total().allocs); 17635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (leaks->Empty()) { 17645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) heap_profile->ReleaseSnapshot(leaks); 17655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) leaks = NULL; 17665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We can only check for internal leaks along the no-user-leak 17685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // path since in the leak path we temporarily release 17695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // heap_checker_lock and another thread can come in and disturb 17705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // allocation counts. 17715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (Allocator::alloc_count() != initial_allocs) { 17725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_LOG(FATAL, "Internal HeapChecker leak of %d objects ; %d -> %d", 17735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Allocator::alloc_count() - initial_allocs, 17745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) initial_allocs, Allocator::alloc_count()); 17755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (FLAGS_heap_check_test_pointer_alignment) { 17775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pointer_source_alignment == 1) { 17785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_LOG(WARNING, "--heap_check_test_pointer_alignment has no effect: " 17795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "--heap_check_pointer_source_alignment was already set to 1"); 17805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 17815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Try with reduced pointer aligment 17825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pointer_source_alignment = 1; 17835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IgnoreAllLiveObjectsLocked(&a_local_var); 17845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapProfileTable::Snapshot* leaks_wo_align = 17855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) heap_profile->NonLiveSnapshot(base); 17865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pointer_source_alignment = FLAGS_heap_check_pointer_source_alignment; 17875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (leaks_wo_align->Empty()) { 17885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_LOG(WARNING, "Found no leaks without pointer alignment: " 17895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "something might be placing pointers at " 17905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "unaligned addresses! This needs to be fixed."); 17915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 17925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_LOG(INFO, "Found leaks without pointer alignment as well: " 17935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "unaligned pointers must not be the cause of leaks."); 17945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_LOG(INFO, "--heap_check_test_pointer_alignment did not help " 17955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "to diagnose the leaks."); 17965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) heap_profile->ReleaseSnapshot(leaks_wo_align); 17985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (leaks != NULL) { 18025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pprof_file = MakeProfileNameLocked(); 18035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) has_checked_ = true; 18075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (leaks == NULL) { 18085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FLAGS_heap_check_max_pointer_offset == -1) { 18095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_LOG(WARNING, 18105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Found no leaks without max_pointer_offset restriction: " 18115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "it's possible that the default value of " 18125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "heap_check_max_pointer_offset flag is too low. " 18135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Do you use pointers with larger than that offsets " 18145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "pointing in the middle of heap-allocated objects?"); 18155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const HeapProfileTable::Stats& stats = heap_profile->total(); 18175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_VLOG(heap_checker_info_level, 18185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "No leaks found for check \"%s\" " 18195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "(but no 100%% guarantee that there aren't any): " 18205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "found %"PRId64" reachable heap objects of %"PRId64" bytes", 18215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name_, 18225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64(stats.allocs - stats.frees), 18235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64(stats.alloc_size - stats.free_size)); 18245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 18255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (should_symbolize == SYMBOLIZE) { 18265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // To turn addresses into symbols, we need to fork, which is a 18275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // problem if both parent and child end up trying to call the 18285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // same malloc-hooks we've set up, at the same time. To avoid 18295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // trouble, we turn off the hooks before symbolizing. Note that 18305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // this makes it unsafe to ever leak-report again! Luckily, we 18315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // typically only want to report once in a program's run, at the 18325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // very end. 18335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (MallocHook::GetNewHook() == NewHook) 18345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MallocHook::SetNewHook(NULL); 18355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (MallocHook::GetDeleteHook() == DeleteHook) 18365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MallocHook::SetDeleteHook(NULL); 18375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MemoryRegionMap::Shutdown(); 18385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure all the hooks really got unset: 18395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_CHECK(MallocHook::GetNewHook() == NULL, ""); 18405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_CHECK(MallocHook::GetDeleteHook() == NULL, ""); 18415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_CHECK(MallocHook::GetMmapHook() == NULL, ""); 18425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_CHECK(MallocHook::GetSbrkHook() == NULL, ""); 18435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) have_disabled_hooks_for_symbolize = true; 18445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) leaks->ReportLeaks(name_, pprof_file, true); // true = should_symbolize 18455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 18465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) leaks->ReportLeaks(name_, pprof_file, false); 18475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FLAGS_heap_check_identify_leaks) { 18495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) leaks->ReportIndividualObjects(); 18505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SuggestPprofCommand(pprof_file); 18535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 18555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpinLockHolder hl(&heap_checker_lock); 18565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) heap_profile->ReleaseSnapshot(leaks); 18575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Allocator::Free(pprof_file); 18585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (leaks == NULL); 18625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 18635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HeapLeakChecker::~HeapLeakChecker() { 18655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (name_ != NULL) { // had leak checking enabled when created the checker 18665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!has_checked_) { 18675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_LOG(FATAL, "Some *NoLeaks|SameHeap method" 18685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) " must be called on any created HeapLeakChecker"); 18695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Deallocate any snapshot taken at start 18725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (start_snapshot_ != NULL) { 18735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpinLockHolder l(&heap_checker_lock); 18745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) heap_profile->ReleaseSnapshot( 18755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<HeapProfileTable::Snapshot*>(start_snapshot_)); 18765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UnIgnoreObject(name_); 18795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete[] name_; 18805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name_ = NULL; 18815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete lock_; 18835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 18845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//---------------------------------------------------------------------- 18865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// HeapLeakChecker overall heap check components 18875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//---------------------------------------------------------------------- 18885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 18905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HeapLeakChecker::IsActive() { 18915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpinLockHolder l(&heap_checker_lock); 18925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return heap_checker_on; 18935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 18945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)vector<HeapCleaner::void_function>* HeapCleaner::heap_cleanups_ = NULL; 18965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// When a HeapCleaner object is intialized, add its function to the static list 18985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of cleaners to be run before leaks checking. 18995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HeapCleaner::HeapCleaner(void_function f) { 19005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (heap_cleanups_ == NULL) 19015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) heap_cleanups_ = new vector<HeapCleaner::void_function>; 19025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) heap_cleanups_->push_back(f); 19035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 19045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Run all of the cleanup functions and delete the vector. 19065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HeapCleaner::RunHeapCleanups() { 19075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!heap_cleanups_) 19085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 19095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < heap_cleanups_->size(); i++) { 19105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void (*f)(void) = (*heap_cleanups_)[i]; 19115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f(); 19125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete heap_cleanups_; 19145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) heap_cleanups_ = NULL; 19155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 19165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Program exit heap cleanup registered as a module object destructor. 19185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Will not get executed when we crash on a signal. 19195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 19205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HeapLeakChecker_RunHeapCleanups() { 19215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FLAGS_heap_check == "local") // don't check heap in this mode 19225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 19235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { SpinLockHolder l(&heap_checker_lock); 19245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // can get here (via forks?) with other pids 19255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (heap_checker_pid != getpid()) return; 19265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapCleaner::RunHeapCleanups(); 19285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!FLAGS_heap_check_after_destructors) HeapLeakChecker::DoMainHeapCheck(); 19295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 19305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool internal_init_start_has_run = false; 19325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Called exactly once, before main() (but hopefully just before). 19345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This picks a good unique name for the dumped leak checking heap profiles. 19355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 19365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Because we crash when InternalInitStart is called more than once, 19375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// it's fine that we hold heap_checker_lock only around pieces of 19385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// this function: this is still enough for thread-safety w.r.t. other functions 19395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of this module. 19405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We can't hold heap_checker_lock throughout because it would deadlock 19415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// on a memory allocation since our new/delete hooks can be on. 19425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 19435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HeapLeakChecker_InternalInitStart() { 19445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { SpinLockHolder l(&heap_checker_lock); 19455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_CHECK(!internal_init_start_has_run, 19465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Heap-check constructor called twice. Perhaps you both linked" 19475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) " in the heap checker, and also used LD_PRELOAD to load it?"); 19485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) internal_init_start_has_run = true; 19495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef ADDRESS_SANITIZER 19515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // AddressSanitizer's custom malloc conflicts with HeapChecker. 19525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FLAGS_heap_check = ""; 19535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 19545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FLAGS_heap_check.empty()) { 19565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // turns out we do not need checking in the end; can stop profiling 19575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapLeakChecker::TurnItselfOffLocked(); 19585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 19595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (RunningOnValgrind()) { 19605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // There is no point in trying -- we'll just fail. 19615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_LOG(WARNING, "Can't run under Valgrind; will turn itself off"); 19625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapLeakChecker::TurnItselfOffLocked(); 19635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 19645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Changing this to false can be useful when debugging heap-checker itself: 19685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!FLAGS_heap_check_run_under_gdb && IsDebuggerAttached()) { 19695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_LOG(WARNING, "Someone is ptrace()ing us; will turn itself off"); 19705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpinLockHolder l(&heap_checker_lock); 19715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapLeakChecker::TurnItselfOffLocked(); 19725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 19735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { SpinLockHolder l(&heap_checker_lock); 19765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!constructor_heap_profiling) { 19775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_LOG(FATAL, "Can not start so late. You have to enable heap checking " 19785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "with HEAPCHECK=<mode>."); 19795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set all flags 19835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_DCHECK(FLAGS_heap_check_pointer_source_alignment > 0, ""); 19845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FLAGS_heap_check == "minimal") { 19855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The least we can check. 19865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FLAGS_heap_check_before_constructors = false; // from after main 19875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (ignore more) 19885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FLAGS_heap_check_after_destructors = false; // to after cleanup 19895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (most data is live) 19905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FLAGS_heap_check_ignore_thread_live = true; // ignore all live 19915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FLAGS_heap_check_ignore_global_live = true; // ignore all live 19925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (FLAGS_heap_check == "normal") { 19935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Faster than 'minimal' and not much stricter. 19945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FLAGS_heap_check_before_constructors = true; // from no profile (fast) 19955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FLAGS_heap_check_after_destructors = false; // to after cleanup 19965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (most data is live) 19975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FLAGS_heap_check_ignore_thread_live = true; // ignore all live 19985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FLAGS_heap_check_ignore_global_live = true; // ignore all live 19995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (FLAGS_heap_check == "strict") { 20005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // A bit stricter than 'normal': global destructors must fully clean up 20015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // after themselves if they are present. 20025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FLAGS_heap_check_before_constructors = true; // from no profile (fast) 20035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FLAGS_heap_check_after_destructors = true; // to after destructors 20045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (less data live) 20055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FLAGS_heap_check_ignore_thread_live = true; // ignore all live 20065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FLAGS_heap_check_ignore_global_live = true; // ignore all live 20075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (FLAGS_heap_check == "draconian") { 20085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Drop not very portable and not very exact live heap flooding. 20095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FLAGS_heap_check_before_constructors = true; // from no profile (fast) 20105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FLAGS_heap_check_after_destructors = true; // to after destructors 20115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (need them) 20125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FLAGS_heap_check_ignore_thread_live = false; // no live flood (stricter) 20135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FLAGS_heap_check_ignore_global_live = false; // no live flood (stricter) 20145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (FLAGS_heap_check == "as-is") { 20155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // do nothing: use other flags as is 20165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (FLAGS_heap_check == "local") { 20175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // do nothing 20185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 20195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_LOG(FATAL, "Unsupported heap_check flag: %s", 20205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FLAGS_heap_check.c_str()); 20215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // FreeBSD doesn't seem to honor atexit execution order: 20235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // http://code.google.com/p/gperftools/issues/detail?id=375 20245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Since heap-checking before destructors depends on atexit running 20255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // at the right time, on FreeBSD we always check after, even in the 20265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // less strict modes. This just means FreeBSD is always a bit 20275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // stricter in its checking than other OSes. 20285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef __FreeBSD__ 20295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FLAGS_heap_check_after_destructors = true; 20305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 20315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { SpinLockHolder l(&heap_checker_lock); 20335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_DCHECK(heap_checker_pid == getpid(), ""); 20345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) heap_checker_on = true; 20355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_DCHECK(heap_profile, ""); 20365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapLeakChecker::ProcMapsResult pm_result = HeapLeakChecker::UseProcMapsLocked(HeapLeakChecker::DISABLE_LIBRARY_ALLOCS); 20375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // might neeed to do this more than once 20385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // if one later dynamically loads libraries that we want disabled 20395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pm_result != HeapLeakChecker::PROC_MAPS_USED) { // can't function 20405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapLeakChecker::TurnItselfOffLocked(); 20415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 20425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // make a good place and name for heap profile leak dumps 20465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) string* profile_prefix = 20475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new string(FLAGS_heap_check_dump_directory + "/" + invocation_name()); 20485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Finalize prefix for dumping leak checking profiles. 20505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const int32 our_pid = getpid(); // safest to call getpid() outside lock 20515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { SpinLockHolder l(&heap_checker_lock); 20525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // main_thread_pid might still be 0 if this function is being called before 20535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // global constructors. In that case, our pid *is* the main pid. 20545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (main_thread_pid == 0) 20555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) main_thread_pid = our_pid; 20565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char pid_buf[15]; 20585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) snprintf(pid_buf, sizeof(pid_buf), ".%d", main_thread_pid); 20595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *profile_prefix += pid_buf; 20605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { SpinLockHolder l(&heap_checker_lock); 20615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_DCHECK(profile_name_prefix == NULL, ""); 20625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_name_prefix = profile_prefix; 20635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure new/delete hooks are installed properly 20665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and heap profiler is indeed able to keep track 20675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // of the objects being allocated. 20685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We test this to make sure we are indeed checking for leaks. 20695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char* test_str = new char[5]; 20705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t size; 20715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { SpinLockHolder l(&heap_checker_lock); 20725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_CHECK(heap_profile->FindAlloc(test_str, &size), 20735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "our own new/delete not linked?"); 20745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete[] test_str; 20765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { SpinLockHolder l(&heap_checker_lock); 20775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This check can fail when it should not if another thread allocates 20785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // into this same spot right this moment, 20795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // which is unlikely since this code runs in InitGoogle. 20805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_CHECK(!heap_profile->FindAlloc(test_str, &size), 20815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "our own new/delete not linked?"); 20825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we crash in the above code, it probably means that 20845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // "nm <this_binary> | grep new" will show that tcmalloc's new/delete 20855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // implementation did not get linked-in into this binary 20865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (i.e. nm will list __builtin_new and __builtin_vec_new as undefined). 20875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If this happens, it is a BUILD bug to be fixed. 20885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_VLOG(heap_checker_info_level, 20905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "WARNING: Perftools heap leak checker is active " 20915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "-- Performance may suffer"); 20925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FLAGS_heap_check != "local") { 20945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapLeakChecker* main_hc = new HeapLeakChecker(); 20955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpinLockHolder l(&heap_checker_lock); 20965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_DCHECK(main_heap_checker == NULL, 20975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Repeated creation of main_heap_checker"); 20985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) main_heap_checker = main_hc; 20995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do_main_heap_check = true; 21005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { SpinLockHolder l(&heap_checker_lock); 21035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_CHECK(heap_checker_on && constructor_heap_profiling, 21045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Leak checking is expected to be fully turned on now"); 21055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For binaries built in debug mode, this will set release queue of 21085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // debugallocation.cc to 100M to make it less likely for real leaks to 21095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // be hidden due to reuse of heap memory object addresses. 21105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Running a test with --malloc_reclaim_memory=0 would help find leaks even 21115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // better, but the test might run out of memory as a result. 21125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The scenario is that a heap object at address X is allocated and freed, 21135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // but some other data-structure still retains a pointer to X. 21145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Then the same heap memory is used for another object, which is leaked, 21155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // but the leak is not noticed due to the pointer to the original object at X. 21165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(csilvers): support this in some manner. 21175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if 0 21185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetCommandLineOptionWithMode("max_free_queue_size", "104857600", // 100M 21195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SET_FLAG_IF_DEFAULT); 21205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 21215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 21225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We want this to run early as well, but not so early as 21245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ::BeforeConstructors (we want flag assignments to have already 21255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// happened, for instance). Initializer-registration does the trick. 21265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_MODULE_INITIALIZER(init_start, HeapLeakChecker_InternalInitStart()); 21275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_MODULE_DESTRUCTOR(init_start, HeapLeakChecker_RunHeapCleanups()); 21285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 21305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HeapLeakChecker::NoGlobalLeaksMaybeSymbolize( 21315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ShouldSymbolize should_symbolize) { 21325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we never delete or change main_heap_checker once it's set: 21335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapLeakChecker* main_hc = GlobalChecker(); 21345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (main_hc) { 21355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_VLOG(10, "Checking for whole-program memory leaks"); 21365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return main_hc->DoNoLeaks(should_symbolize); 21375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 21395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 21405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 21425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HeapLeakChecker::DoMainHeapCheck() { 21435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FLAGS_heap_check_delay_seconds > 0) { 21445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sleep(FLAGS_heap_check_delay_seconds); 21455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { SpinLockHolder l(&heap_checker_lock); 21475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!do_main_heap_check) return false; 21485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_DCHECK(heap_checker_pid == getpid(), ""); 21495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do_main_heap_check = false; // will do it now; no need to do it more 21505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The program is over, so it's safe to symbolize addresses (which 21535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // requires a fork) because no serious work is expected to be done 21545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // after this. Symbolizing is really useful -- knowing what 21555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // function has a leak is better than knowing just an address -- 21565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and while we can only safely symbolize once in a program run, 21575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // now is the time (after all, there's no "later" that would be better). 21585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!NoGlobalLeaksMaybeSymbolize(SYMBOLIZE)) { 21595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FLAGS_heap_check_identify_leaks) { 21605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_LOG(FATAL, "Whole-program memory leaks found."); 21615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_LOG(ERROR, "Exiting with error code (instead of crashing) " 21635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "because of whole-program memory leaks"); 21645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We don't want to call atexit() routines! 21655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) _exit(FLAGS_heap_check_error_exit_code); 21665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 21685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 21695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 21715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HeapLeakChecker* HeapLeakChecker::GlobalChecker() { 21725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpinLockHolder l(&heap_checker_lock); 21735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return main_heap_checker; 21745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 21755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 21775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HeapLeakChecker::NoGlobalLeaks() { 21785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // symbolizing requires a fork, which isn't safe to do in general. 21795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NoGlobalLeaksMaybeSymbolize(DO_NOT_SYMBOLIZE); 21805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 21815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 21835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HeapLeakChecker::CancelGlobalCheck() { 21845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpinLockHolder l(&heap_checker_lock); 21855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (do_main_heap_check) { 21865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_VLOG(heap_checker_info_level, 21875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Canceling the automatic at-exit whole-program memory leak check"); 21885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do_main_heap_check = false; 21895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 21915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 21935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HeapLeakChecker::BeforeConstructorsLocked() { 21945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_DCHECK(heap_checker_lock.IsHeld(), ""); 21955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_CHECK(!constructor_heap_profiling, 21965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "BeforeConstructorsLocked called multiple times"); 21975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef ADDRESS_SANITIZER 21985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // AddressSanitizer's custom malloc conflicts with HeapChecker. 21995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 22005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 22015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set hooks early to crash if 'new' gets called before we make heap_profile, 22025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and make sure no other hooks existed: 22035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_CHECK(MallocHook::AddNewHook(&NewHook), ""); 22045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_CHECK(MallocHook::AddDeleteHook(&DeleteHook), ""); 22055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) constructor_heap_profiling = true; 22062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MemoryRegionMap::Init(1, /* use_buckets */ false); 22075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set up MemoryRegionMap with (at least) one caller stack frame to record 22085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (important that it's done before HeapProfileTable creation below). 22095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Allocator::Init(); 22105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_CHECK(heap_profile == NULL, ""); 22115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) heap_profile = new(Allocator::Allocate(sizeof(HeapProfileTable))) 22122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) HeapProfileTable(&Allocator::Allocate, &Allocator::Free, 22132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) /* profile_mmap */ false); 22145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_VLOG(10, "Starting tracking the heap"); 22155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) heap_checker_on = true; 22165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 22175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 22195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HeapLeakChecker::TurnItselfOffLocked() { 22205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_DCHECK(heap_checker_lock.IsHeld(), ""); 22215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set FLAGS_heap_check to "", for users who test for it 22225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!FLAGS_heap_check.empty()) // be a noop in the common case 22235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FLAGS_heap_check.clear(); // because clear() could allocate memory 22245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (constructor_heap_profiling) { 22255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_CHECK(heap_checker_on, ""); 22265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_VLOG(heap_checker_info_level, "Turning perftools heap leak checking off"); 22275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) heap_checker_on = false; 22285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Unset our hooks checking they were set: 22295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_CHECK(MallocHook::RemoveNewHook(&NewHook), ""); 22305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_CHECK(MallocHook::RemoveDeleteHook(&DeleteHook), ""); 22315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Allocator::DeleteAndNull(&heap_profile); 22325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // free our optional global data: 22335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Allocator::DeleteAndNullIfNot(&ignored_objects); 22345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Allocator::DeleteAndNullIfNot(&disabled_ranges); 22355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Allocator::DeleteAndNullIfNot(&global_region_caller_ranges); 22365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Allocator::Shutdown(); 22375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MemoryRegionMap::Shutdown(); 22385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_CHECK(!heap_checker_on, ""); 22405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 22415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern bool heap_leak_checker_bcad_variable; // in heap-checker-bcad.cc 22435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool has_called_before_constructors = false; 22455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(maxim): inline this function with 22475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MallocHook_InitAtFirstAllocation_HeapLeakChecker, and also rename 22485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// HeapLeakChecker::BeforeConstructorsLocked. 22495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HeapLeakChecker_BeforeConstructors() { 22505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpinLockHolder l(&heap_checker_lock); 22515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We can be called from several places: the first mmap/sbrk/alloc call 22525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // or the first global c-tor from heap-checker-bcad.cc: 22535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Do not re-execute initialization: 22545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (has_called_before_constructors) return; 22555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) has_called_before_constructors = true; 22565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) heap_checker_pid = getpid(); // set it always 22585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) heap_leak_checker_bcad_variable = true; 22595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // just to reference it, so that heap-checker-bcad.o is linked in 22605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This function can be called *very* early, before the normal 22625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // global-constructor that sets FLAGS_verbose. Set it manually now, 22635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // so the RAW_LOG messages here are controllable. 22645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* verbose_str = GetenvBeforeMain("PERFTOOLS_VERBOSE"); 22655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (verbose_str && atoi(verbose_str)) { // different than the default of 0? 22665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FLAGS_verbose = atoi(verbose_str); 22675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool need_heap_check = true; 22705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The user indicates a desire for heap-checking via the HEAPCHECK 22715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // environment variable. If it's not set, there's no way to do 22725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // heap-checking. 22735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!GetenvBeforeMain("HEAPCHECK")) { 22745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) need_heap_check = false; 22755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_GETEUID 22775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (need_heap_check && getuid() != geteuid()) { 22785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // heap-checker writes out files. Thus, for security reasons, we don't 22795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // recognize the env. var. to turn on heap-checking if we're setuid. 22805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_LOG(WARNING, ("HeapChecker: ignoring HEAPCHECK because " 22815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "program seems to be setuid\n")); 22825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) need_heap_check = false; 22835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 22855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (need_heap_check) { 22865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapLeakChecker::BeforeConstructorsLocked(); 22875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 22895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This function overrides the weak function defined in malloc_hook.cc and 22915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// called by one of the initial malloc hooks (malloc_hook.cc) when the very 22925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// first memory allocation or an mmap/sbrk happens. This ensures that 22935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// HeapLeakChecker is initialized and installs all its hooks early enough to 22945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// track absolutely all memory allocations and all memory region acquisitions 22955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// via mmap and sbrk. 22965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" void MallocHook_InitAtFirstAllocation_HeapLeakChecker() { 22975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapLeakChecker_BeforeConstructors(); 22985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 22995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This function is executed after all global object destructors run. 23015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HeapLeakChecker_AfterDestructors() { 23025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { SpinLockHolder l(&heap_checker_lock); 23035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // can get here (via forks?) with other pids 23045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (heap_checker_pid != getpid()) return; 23055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (FLAGS_heap_check_after_destructors) { 23075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (HeapLeakChecker::DoMainHeapCheck()) { 23085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const struct timespec sleep_time = { 0, 500000000 }; // 500 ms 23095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nanosleep(&sleep_time, NULL); 23105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Need this hack to wait for other pthreads to exit. 23115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Otherwise tcmalloc find errors 23125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // on a free() call from pthreads. 23135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SpinLockHolder l(&heap_checker_lock); 23165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_CHECK(!do_main_heap_check, "should have done it"); 23175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 23185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//---------------------------------------------------------------------- 23205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// HeapLeakChecker disabling helpers 23215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//---------------------------------------------------------------------- 23225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// These functions are at the end of the file to prevent their inlining: 23245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 23265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HeapLeakChecker::DisableChecksFromToLocked(const void* start_address, 23275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const void* end_address, 23285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_depth) { 23295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_DCHECK(heap_checker_lock.IsHeld(), ""); 23305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_DCHECK(start_address < end_address, ""); 23315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (disabled_ranges == NULL) { 23325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) disabled_ranges = new(Allocator::Allocate(sizeof(DisabledRangeMap))) 23335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DisabledRangeMap; 23345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RangeValue value; 23365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value.start_address = AsInt(start_address); 23375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value.max_depth = max_depth; 23385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (disabled_ranges->insert(make_pair(AsInt(end_address), value)).second) { 23395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_VLOG(10, "Disabling leak checking in stack traces " 23405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "under frame addresses between %p..%p", 23415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) start_address, end_address); 23425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { // check that this is just a verbatim repetition 23435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RangeValue const& val = disabled_ranges->find(AsInt(end_address))->second; 23445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (val.max_depth != value.max_depth || 23455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) val.start_address != value.start_address) { 23465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_LOG(FATAL, "Two DisableChecksToHereFrom calls conflict: " 23475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "(%p, %p, %d) vs. (%p, %p, %d)", 23485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AsPtr(val.start_address), end_address, val.max_depth, 23495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) start_address, end_address, max_depth); 23505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 23535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 23555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline bool HeapLeakChecker::HaveOnHeapLocked(const void** ptr, 23565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t* object_size) { 23575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Commented-out because HaveOnHeapLocked is very performance-critical: 23585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // RAW_DCHECK(heap_checker_lock.IsHeld(), ""); 23595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uintptr_t addr = AsInt(*ptr); 23605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (heap_profile->FindInsideAlloc( 23615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *ptr, max_heap_object_size, ptr, object_size)) { 23625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_VLOG(16, "Got pointer into %p at +%"PRIuPTR" offset", 23635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *ptr, addr - AsInt(*ptr)); 23645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 23655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 23675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 23685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 23705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const void* HeapLeakChecker::GetAllocCaller(void* ptr) { 23715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // this is used only in the unittest, so the heavy checks are fine 23725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HeapProfileTable::AllocInfo info; 23735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { SpinLockHolder l(&heap_checker_lock); 23745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_CHECK(heap_profile->FindAllocDetails(ptr, &info), ""); 23755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RAW_CHECK(info.stack_depth >= 1, ""); 23775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return info.call_stack[0]; 23785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2379