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, &region)) {
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)            if (!heap_profile->FindAllocDetails(ptr, &alloc)) {
14795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              RAW_LOG(FATAL, "FindAllocDetails failed on ptr %p", ptr);
14805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            }
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;
22065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MemoryRegionMap::Init(1);
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)))
22125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   HeapProfileTable(&Allocator::Allocate, &Allocator::Free);
22135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RAW_VLOG(10, "Starting tracking the heap");
22145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  heap_checker_on = true;
22155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
22165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
22185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HeapLeakChecker::TurnItselfOffLocked() {
22195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RAW_DCHECK(heap_checker_lock.IsHeld(), "");
22205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set FLAGS_heap_check to "", for users who test for it
22215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!FLAGS_heap_check.empty())  // be a noop in the common case
22225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FLAGS_heap_check.clear();     // because clear() could allocate memory
22235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (constructor_heap_profiling) {
22245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RAW_CHECK(heap_checker_on, "");
22255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RAW_VLOG(heap_checker_info_level, "Turning perftools heap leak checking off");
22265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    heap_checker_on = false;
22275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Unset our hooks checking they were set:
22285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RAW_CHECK(MallocHook::RemoveNewHook(&NewHook), "");
22295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RAW_CHECK(MallocHook::RemoveDeleteHook(&DeleteHook), "");
22305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Allocator::DeleteAndNull(&heap_profile);
22315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // free our optional global data:
22325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Allocator::DeleteAndNullIfNot(&ignored_objects);
22335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Allocator::DeleteAndNullIfNot(&disabled_ranges);
22345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Allocator::DeleteAndNullIfNot(&global_region_caller_ranges);
22355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Allocator::Shutdown();
22365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MemoryRegionMap::Shutdown();
22375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
22385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RAW_CHECK(!heap_checker_on, "");
22395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
22405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern bool heap_leak_checker_bcad_variable;  // in heap-checker-bcad.cc
22425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool has_called_before_constructors = false;
22445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(maxim): inline this function with
22465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MallocHook_InitAtFirstAllocation_HeapLeakChecker, and also rename
22475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// HeapLeakChecker::BeforeConstructorsLocked.
22485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HeapLeakChecker_BeforeConstructors() {
22495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SpinLockHolder l(&heap_checker_lock);
22505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We can be called from several places: the first mmap/sbrk/alloc call
22515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // or the first global c-tor from heap-checker-bcad.cc:
22525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Do not re-execute initialization:
22535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (has_called_before_constructors) return;
22545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  has_called_before_constructors = true;
22555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  heap_checker_pid = getpid();  // set it always
22575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  heap_leak_checker_bcad_variable = true;
22585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // just to reference it, so that heap-checker-bcad.o is linked in
22595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This function can be called *very* early, before the normal
22615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // global-constructor that sets FLAGS_verbose.  Set it manually now,
22625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // so the RAW_LOG messages here are controllable.
22635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* verbose_str = GetenvBeforeMain("PERFTOOLS_VERBOSE");
22645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (verbose_str && atoi(verbose_str)) {  // different than the default of 0?
22655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FLAGS_verbose = atoi(verbose_str);
22665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
22675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool need_heap_check = true;
22695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The user indicates a desire for heap-checking via the HEAPCHECK
22705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // environment variable.  If it's not set, there's no way to do
22715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // heap-checking.
22725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!GetenvBeforeMain("HEAPCHECK")) {
22735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    need_heap_check = false;
22745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
22755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_GETEUID
22765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (need_heap_check && getuid() != geteuid()) {
22775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // heap-checker writes out files.  Thus, for security reasons, we don't
22785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // recognize the env. var. to turn on heap-checking if we're setuid.
22795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RAW_LOG(WARNING, ("HeapChecker: ignoring HEAPCHECK because "
22805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      "program seems to be setuid\n"));
22815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    need_heap_check = false;
22825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
22835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
22845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (need_heap_check) {
22855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HeapLeakChecker::BeforeConstructorsLocked();
22865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
22875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
22885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This function overrides the weak function defined in malloc_hook.cc and
22905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// called by one of the initial malloc hooks (malloc_hook.cc) when the very
22915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// first memory allocation or an mmap/sbrk happens.  This ensures that
22925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// HeapLeakChecker is initialized and installs all its hooks early enough to
22935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// track absolutely all memory allocations and all memory region acquisitions
22945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// via mmap and sbrk.
22955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern "C" void MallocHook_InitAtFirstAllocation_HeapLeakChecker() {
22965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HeapLeakChecker_BeforeConstructors();
22975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
22985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This function is executed after all global object destructors run.
23005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HeapLeakChecker_AfterDestructors() {
23015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { SpinLockHolder l(&heap_checker_lock);
23025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // can get here (via forks?) with other pids
23035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (heap_checker_pid != getpid()) return;
23045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
23055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (FLAGS_heap_check_after_destructors) {
23065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (HeapLeakChecker::DoMainHeapCheck()) {
23075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const struct timespec sleep_time = { 0, 500000000 };  // 500 ms
23085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nanosleep(&sleep_time, NULL);
23095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Need this hack to wait for other pthreads to exit.
23105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Otherwise tcmalloc find errors
23115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // on a free() call from pthreads.
23125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
23135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
23145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SpinLockHolder l(&heap_checker_lock);
23155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RAW_CHECK(!do_main_heap_check, "should have done it");
23165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
23175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//----------------------------------------------------------------------
23195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// HeapLeakChecker disabling helpers
23205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//----------------------------------------------------------------------
23215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// These functions are at the end of the file to prevent their inlining:
23235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
23255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HeapLeakChecker::DisableChecksFromToLocked(const void* start_address,
23265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                const void* end_address,
23275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                int max_depth) {
23285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RAW_DCHECK(heap_checker_lock.IsHeld(), "");
23295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RAW_DCHECK(start_address < end_address, "");
23305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (disabled_ranges == NULL) {
23315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    disabled_ranges = new(Allocator::Allocate(sizeof(DisabledRangeMap)))
23325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        DisabledRangeMap;
23335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
23345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RangeValue value;
23355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  value.start_address = AsInt(start_address);
23365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  value.max_depth = max_depth;
23375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (disabled_ranges->insert(make_pair(AsInt(end_address), value)).second) {
23385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RAW_VLOG(10, "Disabling leak checking in stack traces "
23395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                "under frame addresses between %p..%p",
23405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                start_address, end_address);
23415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {  // check that this is just a verbatim repetition
23425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RangeValue const& val = disabled_ranges->find(AsInt(end_address))->second;
23435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (val.max_depth != value.max_depth  ||
23445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        val.start_address != value.start_address) {
23455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RAW_LOG(FATAL, "Two DisableChecksToHereFrom calls conflict: "
23465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     "(%p, %p, %d) vs. (%p, %p, %d)",
23475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     AsPtr(val.start_address), end_address, val.max_depth,
23485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     start_address, end_address, max_depth);
23495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
23505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
23515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
23525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
23545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline bool HeapLeakChecker::HaveOnHeapLocked(const void** ptr,
23555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              size_t* object_size) {
23565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Commented-out because HaveOnHeapLocked is very performance-critical:
23575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // RAW_DCHECK(heap_checker_lock.IsHeld(), "");
23585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uintptr_t addr = AsInt(*ptr);
23595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (heap_profile->FindInsideAlloc(
23605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *ptr, max_heap_object_size, ptr, object_size)) {
23615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RAW_VLOG(16, "Got pointer into %p at +%"PRIuPTR" offset",
23625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             *ptr, addr - AsInt(*ptr));
23635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
23645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
23655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
23665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
23675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
23695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const void* HeapLeakChecker::GetAllocCaller(void* ptr) {
23705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // this is used only in the unittest, so the heavy checks are fine
23715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HeapProfileTable::AllocInfo info;
23725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { SpinLockHolder l(&heap_checker_lock);
23735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RAW_CHECK(heap_profile->FindAllocDetails(ptr, &info), "");
23745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
23755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RAW_CHECK(info.stack_depth >= 1, "");
23765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return info.call_stack[0];
23775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2378