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)// Author: Maxim Lifantsev
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Running:
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ./heap-checker_unittest
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If the unittest crashes because it can't find pprof, try:
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// PPROF_PATH=/usr/local/someplace/bin/pprof ./heap-checker_unittest
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// To test that the whole-program heap checker will actually cause a leak, try:
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// HEAPCHECK_TEST_LEAK= ./heap-checker_unittest
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// HEAPCHECK_TEST_LOOP_LEAK= ./heap-checker_unittest
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note: Both of the above commands *should* abort with an error message.
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CAVEAT: Do not use vector<> and string on-heap objects in this test,
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// otherwise the test can sometimes fail for tricky leak checks
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// when we want some allocated object not to be found live by the heap checker.
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This can happen with memory allocators like tcmalloc that can allocate
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// heap objects back to back without any book-keeping data in between.
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// What happens is that end-of-storage pointers of a live vector
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (or a string depending on the STL implementation used)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// can happen to point to that other heap-allocated
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// object that is not reachable otherwise and that
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// we don't want to be reachable.
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The implication of this for real leak checking
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is just one more chance for the liveness flood to be inexact
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (see the comment in our .h file).
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "config_for_unittests.h"
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_POLL_H
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <poll.h>
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined HAVE_STDINT_H
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdint.h>             // to get uint16_t (ISO naming madness)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined HAVE_INTTYPES_H
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <inttypes.h>           // another place uint16_t might be defined
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/types.h>
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <stdlib.h>
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <errno.h>              // errno
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_UNISTD_H
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <unistd.h>             // for sleep(), geteuid()
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_MMAP
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sys/mman.h>
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <fcntl.h>              // for open(), close()
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_EXECINFO_H
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <execinfo.h>           // backtrace
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_GRP_H
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <grp.h>                // getgrent, getgrnam
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_PWD_H
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <pwd.h>
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <iostream>             // for cout
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <iomanip>              // for hex
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <list>
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map>
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <memory>
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set>
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/commandlineflags.h"
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/googleinit.h"
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/commandlineflags.h"
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/thread_lister.h"
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <gperftools/heap-checker.h>
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "memory_region_map.h"
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <gperftools/malloc_extension.h>
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <gperftools/stacktrace.h>
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// On systems (like freebsd) that don't define MAP_ANONYMOUS, use the old
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// form of the name instead.
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef MAP_ANONYMOUS
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# define MAP_ANONYMOUS MAP_ANON
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using namespace std;
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ========================================================================= //
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(maxim): write a shell script to test that these indeed crash us
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//              (i.e. we do detect leaks)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//              Maybe add more such crash tests.
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEFINE_bool(test_leak,
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            EnvToBool("HEAP_CHECKER_TEST_TEST_LEAK", false),
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            "If should cause a leak crash");
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEFINE_bool(test_loop_leak,
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            EnvToBool("HEAP_CHECKER_TEST_TEST_LOOP_LEAK", false),
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            "If should cause a looped leak crash");
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEFINE_bool(test_register_leak,
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            EnvToBool("HEAP_CHECKER_TEST_TEST_REGISTER_LEAK", false),
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            "If should cause a leak crash by hiding a pointer "
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            "that is only in a register");
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEFINE_bool(test_cancel_global_check,
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            EnvToBool("HEAP_CHECKER_TEST_TEST_CANCEL_GLOBAL_CHECK", false),
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            "If should test HeapLeakChecker::CancelGlobalCheck "
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            "when --test_leak or --test_loop_leak are given; "
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            "the test should not fail then");
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEFINE_bool(maybe_stripped,
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            EnvToBool("HEAP_CHECKER_TEST_MAYBE_STRIPPED", true),
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            "If we think we can be a stripped binary");
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEFINE_bool(interfering_threads,
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            EnvToBool("HEAP_CHECKER_TEST_INTERFERING_THREADS", true),
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            "If we should use threads trying "
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            "to interfere with leak checking");
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEFINE_bool(hoarding_threads,
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            EnvToBool("HEAP_CHECKER_TEST_HOARDING_THREADS", true),
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            "If threads (usually the manager thread) are known "
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            "to retain some old state in their global buffers, "
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            "so that it's hard to force leaks when threads are around");
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // TODO(maxim): Chage the default to false
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // when the standard environment used NTPL threads:
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // they do not seem to have this problem.
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DEFINE_bool(no_threads,
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            EnvToBool("HEAP_CHECKER_TEST_NO_THREADS", false),
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            "If we should not use any threads");
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // This is used so we can make can_create_leaks_reliably true
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            // for any pthread implementation and test with that.
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DECLARE_int64(heap_check_max_pointer_offset);   // heap-checker.cc
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DECLARE_string(heap_check);  // in heap-checker.cc
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define WARN_IF(cond, msg)   LOG_IF(WARNING, cond, msg)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This is an evil macro!  Be very careful using it...
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef VLOG          // and we start by evilling overriding logging.h VLOG
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define VLOG(lvl)    if (FLAGS_verbose >= (lvl))  cout << "\n"
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This is, likewise, evil
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define LOGF         VLOG(INFO)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void RunHeapBusyThreads();  // below
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Closure {
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~Closure() { }
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Run() = 0;
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Callback0 : public Closure {
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef void (*FunctionSignature)();
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Callback0(FunctionSignature f) : f_(f) {}
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Run() { (*f_)(); delete this; }
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FunctionSignature f_;
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <class P1> class Callback1 : public Closure {
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef void (*FunctionSignature)(P1);
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Callback1<P1>(FunctionSignature f, P1 p1) : f_(f), p1_(p1) {}
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Run() { (*f_)(p1_); delete this; }
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FunctionSignature f_;
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  P1 p1_;
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <class P1, class P2> class Callback2 : public Closure {
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef void (*FunctionSignature)(P1,P2);
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  inline Callback2<P1,P2>(FunctionSignature f, P1 p1, P2 p2) : f_(f), p1_(p1), p2_(p2) {}
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void Run() { (*f_)(p1_, p2_); delete this; }
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FunctionSignature f_;
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  P1 p1_;
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  P2 p2_;
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Callback0* NewCallback(void (*function)()) {
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new Callback0(function);
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <class P1>
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Callback1<P1>* NewCallback(void (*function)(P1), P1 p1) {
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new Callback1<P1>(function, p1);
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <class P1, class P2>
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline Callback2<P1,P2>* NewCallback(void (*function)(P1,P2), P1 p1, P2 p2) {
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return new Callback2<P1,P2>(function, p1, p2);
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Set to true at end of main, so threads know.  Not entirely thread-safe!,
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// but probably good enough.
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool g_have_exited_main = false;
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If we can reliably create leaks (i.e. make leaked object
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// really unreachable from any global data).
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool can_create_leaks_reliably = false;
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We use a simple allocation wrapper
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to make sure we wipe out the newly allocated objects
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in case they still happened to contain some pointer data
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// accidentally left by the memory allocator.
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct Initialized { };
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static Initialized initialized;
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* operator new(size_t size, const Initialized&) {
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Below we use "p = new(initialized) Foo[1];" and  "delete[] p;"
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // instead of "p = new(initialized) Foo;"
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // when we need to delete an allocated object.
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* p = malloc(size);
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(p, 0, size);
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return p;
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void* operator new[](size_t size, const Initialized&) {
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char* p = new char[size];
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(p, 0, size);
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return p;
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void DoWipeStack(int n);  // defined below
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void WipeStack() { DoWipeStack(20); }
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void Pause() {
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  poll(NULL, 0, 77);  // time for thread activity in HeapBusyThreadBody
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Indirectly test malloc_extension.*:
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(MallocExtension::instance()->VerifyAllMemory());
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int blocks;
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t total;
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int histogram[kMallocHistogramSize];
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (MallocExtension::instance()
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ->MallocMemoryStats(&blocks, &total, histogram)  &&  total != 0) {
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(3) << "Malloc stats: " << blocks << " blocks of "
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << total << " bytes";
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < kMallocHistogramSize; ++i) {
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (histogram[i]) {
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        VLOG(3) << "  Malloc histogram at " << i << " : " << histogram[i];
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WipeStack();  // e.g. MallocExtension::VerifyAllMemory
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                // can leave pointers to heap objects on stack
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Make gcc think a pointer is "used"
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <class T>
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void Use(T** foo) {
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(2) << "Dummy-using " << static_cast<void*>(*foo) << " at " << foo;
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Arbitrary value, but not such that xor'ing with it is likely
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to map one valid pointer to another valid pointer:
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const uintptr_t kHideMask =
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static_cast<uintptr_t>(0xF03A5F7BF03A5F7BLL);
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helpers to hide a pointer from live data traversal.
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We just xor the pointer so that (with high probability)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// it's not a valid address of a heap object anymore.
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Both Hide and UnHide must be executed within RunHidden() below
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to prevent leaving stale data on active stack that can be a pointer
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to a heap object that is not actually reachable via live variables.
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (UnHide might leave heap pointer value for an object
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  that will be deallocated but later another object
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  can be allocated at the same heap address.)
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <class T>
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void Hide(T** ptr) {
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // we cast values, not dereferenced pointers, so no aliasing issues:
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *ptr = reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(*ptr) ^ kHideMask);
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(2) << "hid: " << static_cast<void*>(*ptr);
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <class T>
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void UnHide(T** ptr) {
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(2) << "unhiding: " << static_cast<void*>(*ptr);
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // we cast values, not dereferenced pointers, so no aliasing issues:
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *ptr = reinterpret_cast<T*>(reinterpret_cast<uintptr_t>(*ptr) ^ kHideMask);
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void LogHidden(const char* message, const void* ptr) {
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOGF << message << " : "
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       << ptr << " ^ " << reinterpret_cast<void*>(kHideMask) << endl;
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// volatile to fool the compiler against inlining the calls to these
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void (*volatile run_hidden_ptr)(Closure* c, int n);
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void (*volatile wipe_stack_ptr)(int n);
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void DoRunHidden(Closure* c, int n) {
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (n) {
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(10) << "Level " << n << " at " << &n;
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*run_hidden_ptr)(c, n-1);
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*wipe_stack_ptr)(n);
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sleep(0);  // undo -foptimize-sibling-calls
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    c->Run();
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*static*/ void DoWipeStack(int n) {
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(10) << "Wipe level " << n << " at " << &n;
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (n) {
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const int sz = 30;
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    volatile int arr[sz];
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < sz; ++i) arr[i] = 0;
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*wipe_stack_ptr)(n-1);
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    sleep(0);  // undo -foptimize-sibling-calls
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This executes closure c several stack frames down from the current one
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and then makes an effort to also wipe out the stack data that was used by
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the closure.
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This way we prevent leak checker from finding any temporary pointers
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of the closure execution on the stack and deciding that
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// these pointers (and the pointed objects) are still live.
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void RunHidden(Closure* c) {
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DoRunHidden(c, 15);
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DoWipeStack(20);
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void DoAllocHidden(size_t size, void** ptr) {
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* p = new(initialized) char[size];
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Hide(&p);
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Use(&p);  // use only hidden versions
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(2) << "Allocated hidden " << p << " at " << &p;
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *ptr = p;  // assign the hidden versions
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void* AllocHidden(size_t size) {
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* r;
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunHidden(NewCallback(DoAllocHidden, size, &r));
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return r;
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void DoDeAllocHidden(void** ptr) {
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Use(ptr);  // use only hidden versions
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* p = *ptr;
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(2) << "Deallocating hidden " << p;
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UnHide(&p);
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete [] reinterpret_cast<char*>(p);
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void DeAllocHidden(void** ptr) {
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunHidden(NewCallback(DoDeAllocHidden, ptr));
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *ptr = NULL;
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Use(ptr);
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PreventHeapReclaiming(size_t size) {
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef NDEBUG
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (true) {
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    static void** no_reclaim_list = NULL;
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(size >= sizeof(void*));
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We can't use malloc_reclaim_memory flag in opt mode as debugallocation.cc
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // is not used. Instead we allocate a bunch of heap objects that are
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // of the same size as what we are going to leak to ensure that the object
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // we are about to leak is not at the same address as some old allocated
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // and freed object that might still have pointers leading to it.
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < 100; ++i) {
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      void** p = reinterpret_cast<void**>(new(initialized) char[size]);
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      p[0] = no_reclaim_list;
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      no_reclaim_list = p;
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool RunSilent(HeapLeakChecker* check,
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      bool (HeapLeakChecker::* func)()) {
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // By default, don't print the 'we detected a leak' message in the
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // cases we're expecting a leak (we still print when --v is >= 1).
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This way, the logging output is less confusing: we only print
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // "we detected a leak", and how to diagnose it, for *unexpected* leaks.
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int32 old_FLAGS_verbose = FLAGS_verbose;
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!VLOG_IS_ON(1))             // not on a verbose setting
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    FLAGS_verbose = FATAL;        // only log fatal errors
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool retval = (check->*func)();
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FLAGS_verbose = old_FLAGS_verbose;
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return retval;
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define RUN_SILENT(check, func)  RunSilent(&(check), &HeapLeakChecker::func)
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum CheckType { SAME_HEAP, NO_LEAKS };
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void VerifyLeaks(HeapLeakChecker* check, CheckType type,
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        int leaked_bytes, int leaked_objects) {
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WipeStack();  // to help with can_create_leaks_reliably
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool no_leaks =
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    type == NO_LEAKS ? RUN_SILENT(*check, BriefNoLeaks)
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     : RUN_SILENT(*check, BriefSameHeap);
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (can_create_leaks_reliably) {
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // these might still fail occasionally, but it should be very rare
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK_EQ(no_leaks, false);
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK_EQ(check->BytesLeaked(), leaked_bytes);
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK_EQ(check->ObjectsLeaked(), leaked_objects);
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WARN_IF(no_leaks != false,
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            "Expected leaks not found: "
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            "Some liveness flood must be too optimistic");
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// not deallocates
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestHeapLeakCheckerDeathSimple() {
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HeapLeakChecker check("death_simple");
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* foo = AllocHidden(100 * sizeof(int));
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Use(&foo);
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* bar = AllocHidden(300);
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Use(&bar);
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LogHidden("Leaking", foo);
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LogHidden("Leaking", bar);
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Pause();
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VerifyLeaks(&check, NO_LEAKS, 300 + 100 * sizeof(int), 2);
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeAllocHidden(&foo);
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeAllocHidden(&bar);
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void MakeDeathLoop(void** arr1, void** arr2) {
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PreventHeapReclaiming(2 * sizeof(void*));
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void** a1 = new(initialized) void*[2];
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void** a2 = new(initialized) void*[2];
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  a1[1] = reinterpret_cast<void*>(a2);
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  a2[1] = reinterpret_cast<void*>(a1);
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Hide(&a1);
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Hide(&a2);
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Use(&a1);
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Use(&a2);
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(2) << "Made hidden loop at " << &a1 << " to " << arr1;
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *arr1 = a1;
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *arr2 = a2;
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// not deallocates two objects linked together
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestHeapLeakCheckerDeathLoop() {
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HeapLeakChecker check("death_loop");
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* arr1;
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* arr2;
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunHidden(NewCallback(MakeDeathLoop, &arr1, &arr2));
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Use(&arr1);
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Use(&arr2);
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LogHidden("Leaking", arr1);
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LogHidden("Leaking", arr2);
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Pause();
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VerifyLeaks(&check, NO_LEAKS, 4 * sizeof(void*), 2);
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeAllocHidden(&arr1);
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeAllocHidden(&arr2);
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// deallocates more than allocates
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestHeapLeakCheckerDeathInverse() {
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* bar = AllocHidden(250 * sizeof(int));
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Use(&bar);
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LogHidden("Pre leaking", bar);
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Pause();
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HeapLeakChecker check("death_inverse");
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* foo = AllocHidden(100 * sizeof(int));
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Use(&foo);
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LogHidden("Leaking", foo);
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeAllocHidden(&bar);
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Pause();
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VerifyLeaks(&check, SAME_HEAP,
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              100 * static_cast<int64>(sizeof(int)),
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              1);
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeAllocHidden(&foo);
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// deallocates more than allocates
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestHeapLeakCheckerDeathNoLeaks() {
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* foo = AllocHidden(100 * sizeof(int));
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Use(&foo);
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* bar = AllocHidden(250 * sizeof(int));
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Use(&bar);
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HeapLeakChecker check("death_noleaks");
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeAllocHidden(&bar);
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_EQ(check.BriefNoLeaks(), true);
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeAllocHidden(&foo);
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// have less objecs
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestHeapLeakCheckerDeathCountLess() {
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* bar1 = AllocHidden(50 * sizeof(int));
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Use(&bar1);
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* bar2 = AllocHidden(50 * sizeof(int));
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Use(&bar2);
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LogHidden("Pre leaking", bar1);
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LogHidden("Pre leaking", bar2);
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Pause();
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HeapLeakChecker check("death_count_less");
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* foo = AllocHidden(100 * sizeof(int));
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Use(&foo);
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LogHidden("Leaking", foo);
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeAllocHidden(&bar1);
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeAllocHidden(&bar2);
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Pause();
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VerifyLeaks(&check, SAME_HEAP,
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              100 * sizeof(int),
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              1);
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeAllocHidden(&foo);
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// have more objecs
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestHeapLeakCheckerDeathCountMore() {
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* foo = AllocHidden(100 * sizeof(int));
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Use(&foo);
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LogHidden("Pre leaking", foo);
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Pause();
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HeapLeakChecker check("death_count_more");
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* bar1 = AllocHidden(50 * sizeof(int));
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Use(&bar1);
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* bar2 = AllocHidden(50 * sizeof(int));
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Use(&bar2);
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LogHidden("Leaking", bar1);
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LogHidden("Leaking", bar2);
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeAllocHidden(&foo);
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Pause();
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VerifyLeaks(&check, SAME_HEAP,
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              100 * sizeof(int),
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              2);
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeAllocHidden(&bar1);
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeAllocHidden(&bar2);
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestHiddenPointer() {
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i;
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* foo = &i;
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HiddenPointer<void> p(foo);
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_EQ(foo, p.get());
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Confirm pointer doesn't appear to contain a byte sequence
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // that == the pointer.  We don't really need to test that
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the xor trick itself works, as without it nothing in this
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // test suite would work.  See the Hide/Unhide/*Hidden* set
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // of helper methods.
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_NE(foo, *reinterpret_cast<void**>(&p));
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// simple tests that deallocate what they allocated
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestHeapLeakChecker() {
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { HeapLeakChecker check("trivial");
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int foo = 5;
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int* p = &foo;
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Use(&p);
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Pause();
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(check.BriefSameHeap());
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Pause();
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { HeapLeakChecker check("simple");
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* foo = AllocHidden(100 * sizeof(int));
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Use(&foo);
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* bar = AllocHidden(200 * sizeof(int));
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Use(&bar);
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DeAllocHidden(&foo);
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DeAllocHidden(&bar);
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Pause();
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(check.BriefSameHeap());
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// no false positives
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestHeapLeakCheckerNoFalsePositives() {
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { HeapLeakChecker check("trivial_p");
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int foo = 5;
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int* p = &foo;
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Use(&p);
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Pause();
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(check.BriefSameHeap());
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Pause();
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { HeapLeakChecker check("simple_p");
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* foo = AllocHidden(100 * sizeof(int));
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Use(&foo);
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* bar = AllocHidden(200 * sizeof(int));
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Use(&bar);
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DeAllocHidden(&foo);
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DeAllocHidden(&bar);
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Pause();
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(check.SameHeap());
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// test that we detect leaks when we have same total # of bytes and
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// objects, but different individual object sizes
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestLeakButTotalsMatch() {
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* bar1 = AllocHidden(240 * sizeof(int));
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Use(&bar1);
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* bar2 = AllocHidden(160 * sizeof(int));
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Use(&bar2);
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LogHidden("Pre leaking", bar1);
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LogHidden("Pre leaking", bar2);
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Pause();
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HeapLeakChecker check("trick");
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* foo1 = AllocHidden(280 * sizeof(int));
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Use(&foo1);
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* foo2 = AllocHidden(120 * sizeof(int));
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Use(&foo2);
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LogHidden("Leaking", foo1);
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LogHidden("Leaking", foo2);
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeAllocHidden(&bar1);
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeAllocHidden(&bar2);
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Pause();
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // foo1 and foo2 leaked
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VerifyLeaks(&check, NO_LEAKS, (280+120)*sizeof(int), 2);
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeAllocHidden(&foo1);
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeAllocHidden(&foo2);
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// no false negatives from pprof
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestHeapLeakCheckerDeathTrick() {
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* bar1 = AllocHidden(240 * sizeof(int));
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Use(&bar1);
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* bar2 = AllocHidden(160 * sizeof(int));
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Use(&bar2);
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HeapLeakChecker check("death_trick");
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeAllocHidden(&bar1);
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeAllocHidden(&bar2);
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* foo1 = AllocHidden(280 * sizeof(int));
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Use(&foo1);
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* foo2 = AllocHidden(120 * sizeof(int));
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Use(&foo2);
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(maxim): use the above if we make pprof work in automated test runs
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!FLAGS_maybe_stripped) {
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK_EQ(RUN_SILENT(check, SameHeap), false);
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // pprof checking should catch the leak
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WARN_IF(RUN_SILENT(check, SameHeap) != false,
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            "death_trick leak is not caught; "
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            "we must be using a stripped binary");
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeAllocHidden(&foo1);
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeAllocHidden(&foo2);
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// simple leak
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TransLeaks() {
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AllocHidden(1 * sizeof(char));
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// range-based disabling using Disabler
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void ScopedDisabledLeaks() {
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HeapLeakChecker::Disabler disabler;
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AllocHidden(3 * sizeof(int));
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TransLeaks();
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  (void)malloc(10);  // Direct leak
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// have different disabled leaks
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void* RunDisabledLeaks(void* a) {
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScopedDisabledLeaks();
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return a;
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// have different disabled leaks inside of a thread
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void ThreadDisabledLeaks() {
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (FLAGS_no_threads)  return;
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pthread_t tid;
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pthread_attr_t attr;
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_EQ(pthread_attr_init(&attr), 0);
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_EQ(pthread_create(&tid, &attr, RunDisabledLeaks, NULL), 0);
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* res;
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_EQ(pthread_join(tid, &res), 0);
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// different disabled leaks (some in threads)
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestHeapLeakCheckerDisabling() {
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HeapLeakChecker check("disabling");
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunDisabledLeaks(NULL);
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunDisabledLeaks(NULL);
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ThreadDisabledLeaks();
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunDisabledLeaks(NULL);
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ThreadDisabledLeaks();
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ThreadDisabledLeaks();
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Pause();
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(check.SameHeap());
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef set<int> IntSet;
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int some_ints[] = { 1, 2, 3, 21, 22, 23, 24, 25 };
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void DoTestSTLAlloc() {
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IntSet* x = new(initialized) IntSet[1];
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *x = IntSet(some_ints, some_ints + 6);
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < 1000; i++) {
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    x->insert(i*3);
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete [] x;
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Check that normal STL usage does not result in a leak report.
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (In particular we test that there's no complex STL's own allocator
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// running on top of our allocator with hooks to heap profiler
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that can result in false leak report in this case.)
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestSTLAlloc() {
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HeapLeakChecker check("stl");
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunHidden(NewCallback(DoTestSTLAlloc));
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_EQ(check.BriefSameHeap(), true);
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void DoTestSTLAllocInverse(IntSet** setx) {
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IntSet* x = new(initialized) IntSet[1];
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *x = IntSet(some_ints, some_ints + 3);
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < 100; i++) {
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    x->insert(i*2);
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Hide(&x);
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *setx = x;
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void FreeTestSTLAllocInverse(IntSet** setx) {
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IntSet* x = *setx;
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UnHide(&x);
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete [] x;
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Check that normal leaked STL usage *does* result in a leak report.
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// (In particular we test that there's no complex STL's own allocator
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// running on top of our allocator with hooks to heap profiler
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that can result in false absence of leak report in this case.)
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestSTLAllocInverse() {
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HeapLeakChecker check("death_inverse_stl");
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IntSet* x;
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunHidden(NewCallback(DoTestSTLAllocInverse, &x));
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LogHidden("Leaking", x);
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (can_create_leaks_reliably) {
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WipeStack();  // to help with can_create_leaks_reliably
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // these might still fail occasionally, but it should be very rare
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK_EQ(RUN_SILENT(check, BriefNoLeaks), false);
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK_GE(check.BytesLeaked(), 100 * sizeof(int));
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK_GE(check.ObjectsLeaked(), 100);
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // assumes set<>s are represented by some kind of binary tree
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // or something else allocating >=1 heap object per set object
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WARN_IF(RUN_SILENT(check, BriefNoLeaks) != false,
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            "Expected leaks not found: "
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            "Some liveness flood must be too optimistic");
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RunHidden(NewCallback(FreeTestSTLAllocInverse, &x));
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<class Alloc>
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void DirectTestSTLAlloc(Alloc allocator, const char* name) {
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HeapLeakChecker check((string("direct_stl-") + name).c_str());
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const int kSize = 1000;
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typename Alloc::pointer ptrs[kSize];
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < kSize; ++i) {
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    typename Alloc::pointer p = allocator.allocate(i*3+1);
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HeapLeakChecker::IgnoreObject(p);
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This will crash if p is not known to heap profiler:
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // (i.e. STL's "allocator" does not have a direct hook to heap profiler)
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HeapLeakChecker::UnIgnoreObject(p);
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ptrs[i] = p;
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < kSize; ++i) {
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    allocator.deallocate(ptrs[i], i*3+1);
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ptrs[i] = NULL;
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(check.BriefSameHeap());  // just in case
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static struct group* grp = NULL;
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kKeys = 50;
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static pthread_key_t key[kKeys];
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void KeyFree(void* ptr) {
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete [] reinterpret_cast<char*>(ptr);
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool key_init_has_run = false;
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void KeyInit() {
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < kKeys; ++i) {
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK_EQ(pthread_key_create(&key[i], KeyFree), 0);
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(2) << "pthread key " << i << " : " << key[i];
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  key_init_has_run = true;   // needed for a sanity-check
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// force various C library static and thread-specific allocations
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestLibCAllocate() {
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(key_init_has_run);
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < kKeys; ++i) {
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* p = pthread_getspecific(key[i]);
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (NULL == p) {
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (i == 0) {
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Test-logging inside threads which (potentially) creates and uses
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // thread-local data inside standard C++ library:
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        VLOG(0) << "Adding pthread-specifics for thread " << pthread_self()
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                << " pid " << getpid();
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      p = new(initialized) char[77 + i];
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      VLOG(2) << "pthread specific " << i << " : " << p;
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pthread_setspecific(key[i], p);
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  strerror(errno);
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const time_t now = time(NULL);
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ctime(&now);
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_EXECINFO_H
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void *stack[1];
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  backtrace(stack, 1);
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_GRP_H
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gid_t gid = getgid();
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  getgrgid(gid);
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (grp == NULL)  grp = getgrent();  // a race condition here is okay
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  getgrnam(grp->gr_name);
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef HAVE_PWD_H
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  getpwuid(geteuid());
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Continuous random heap memory activity to try to disrupt heap checking.
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void* HeapBusyThreadBody(void* a) {
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int thread_num = reinterpret_cast<intptr_t>(a);
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(0) << "A new HeapBusyThread " << thread_num;
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestLibCAllocate();
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int user = 0;
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Try to hide ptr from heap checker in a CPU register:
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Here we are just making a best effort to put the only pointer
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to a heap object into a thread register to test
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the thread-register finding machinery in the heap checker.
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(__i386__) && defined(__GNUC__)
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  register int** ptr asm("esi");
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(__x86_64__) && defined(__GNUC__)
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  register int** ptr asm("r15");
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  register int** ptr;
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ptr = NULL;
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef set<int> Set;
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Set s1;
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (1) {
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TestLibCAllocate() calls libc functions that don't work so well
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // after main() has exited.  So we just don't do the test then.
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!g_have_exited_main)
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TestLibCAllocate();
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ptr == NULL) {
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ptr = new(initialized) int*[1];
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *ptr = new(initialized) int[1];
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    set<int>* s2 = new(initialized) set<int>[1];
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    s1.insert(random());
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    s2->insert(*s1.begin());
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    user += *s2->begin();
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    **ptr += user;
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (random() % 51 == 0) {
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      s1.clear();
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (random() % 2 == 0) {
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        s1.~Set();
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new(&s1) Set;
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(3) << pthread_self() << " (" << getpid() << "): in wait: "
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << ptr << ", " << *ptr << "; " << s1.size();
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(2) << pthread_self() << " (" << getpid() << "): in wait, ptr = "
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << reinterpret_cast<void*>(
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 reinterpret_cast<uintptr_t>(ptr) ^ kHideMask)
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << "^" << reinterpret_cast<void*>(kHideMask);
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (FLAGS_test_register_leak  &&  thread_num % 5 == 0) {
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Hide the register "ptr" value with an xor mask.
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // If one provides --test_register_leak flag, the test should
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // (with very high probability) crash on some leak check
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // with a leak report (of some x * sizeof(int) + y * sizeof(int*) bytes)
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // pointing at the two lines above in this function
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // with "new(initialized) int" in them as the allocators
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // of the leaked objects.
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // CAVEAT: We can't really prevent a compiler to save some
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // temporary values of "ptr" on the stack and thus let us find
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // the heap objects not via the register.
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Hence it's normal if for certain compilers or optimization modes
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // --test_register_leak does not cause a leak crash of the above form
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // (this happens e.g. for gcc 4.0.1 in opt mode).
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ptr = reinterpret_cast<int **>(
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          reinterpret_cast<uintptr_t>(ptr) ^ kHideMask);
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // busy loop to get the thread interrupted at:
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (int i = 1; i < 10000000; ++i)  user += (1 + user * user * 5) / i;
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ptr = reinterpret_cast<int **>(
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          reinterpret_cast<uintptr_t>(ptr) ^ kHideMask);
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      poll(NULL, 0, random() % 100);
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(2) << pthread_self() << ": continuing";
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (random() % 3 == 0) {
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete [] *ptr;
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete [] ptr;
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ptr = NULL;
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete [] s2;
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return a;
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void RunHeapBusyThreads() {
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  KeyInit();
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!FLAGS_interfering_threads || FLAGS_no_threads)  return;
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int n = 17;  // make many threads
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pthread_t tid;
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pthread_attr_t attr;
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_EQ(pthread_attr_init(&attr), 0);
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // make them and let them run
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < n; ++i) {
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(0) << "Creating extra thread " << i + 1;
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(pthread_create(&tid, &attr, HeapBusyThreadBody,
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         reinterpret_cast<void*>(i)) == 0);
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Pause();
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Pause();
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ========================================================================= //
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This code section is to test that objects that are reachable from global
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// variables are not reported as leaks
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// as well as that (Un)IgnoreObject work for such objects fine.
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// An object making functions:
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// returns a "weird" pointer to a new object for which
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// it's worth checking that the object is reachable via that pointer.
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef void* (*ObjMakerFunc)();
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static list<ObjMakerFunc> obj_makers;  // list of registered object makers
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper macro to register an object making function
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 'name' is an identifier of this object maker,
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 'body' is its function body that must declare
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//        pointer 'p' to the nex object to return.
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Usage example:
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   REGISTER_OBJ_MAKER(trivial, int* p = new(initialized) int;)
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define REGISTER_OBJ_MAKER(name, body) \
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* ObjMaker_##name##_() { \
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "Obj making " << #name; \
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    body; \
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return p; \
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } \
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static ObjMakerRegistrar maker_reg_##name##__(&ObjMaker_##name##_);
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// helper class for REGISTER_OBJ_MAKER
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct ObjMakerRegistrar {
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ObjMakerRegistrar(ObjMakerFunc obj_maker) { obj_makers.push_back(obj_maker); }
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// List of the objects/pointers made with all the obj_makers
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to test reachability via global data pointers during leak checks.
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static list<void*>* live_objects = new list<void*>;
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // pointer so that it does not get destructed on exit
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Exerciser for one ObjMakerFunc.
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestPointerReach(ObjMakerFunc obj_maker) {
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HeapLeakChecker::IgnoreObject(obj_maker());  // test IgnoreObject
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* obj = obj_maker();
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HeapLeakChecker::IgnoreObject(obj);
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HeapLeakChecker::UnIgnoreObject(obj);  // test UnIgnoreObject
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HeapLeakChecker::IgnoreObject(obj);  // not to need deletion for obj
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  live_objects->push_back(obj_maker());  // test reachability at leak check
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test all ObjMakerFunc registred via REGISTER_OBJ_MAKER.
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestObjMakers() {
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (list<ObjMakerFunc>::const_iterator i = obj_makers.begin();
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != obj_makers.end(); ++i) {
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TestPointerReach(*i);
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TestPointerReach(*i);  // a couple more times would not hurt
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TestPointerReach(*i);
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A dummy class to mimic allocation behavior of string-s.
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<class T>
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct Array {
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Array() {
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size = 3 + random() % 30;
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ptr = new(initialized) T[size];
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~Array() { delete [] ptr; }
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Array(const Array& x) {
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size = x.size;
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ptr = new(initialized) T[size];
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < size; ++i) {
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ptr[i] = x.ptr[i];
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void operator=(const Array& x) {
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete [] ptr;
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size = x.size;
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ptr = new(initialized) T[size];
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < size; ++i) {
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ptr[i] = x.ptr[i];
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void append(const Array& x) {
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    T* p = new(initialized) T[size + x.size];
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < size; ++i) {
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      p[i] = ptr[i];
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < x.size; ++i) {
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      p[size+i] = x.ptr[i];
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size += x.size;
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete [] ptr;
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ptr = p;
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t size;
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  T* ptr;
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to test pointers to objects, built-in arrays, string, etc:
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(plain, int* p = new(initialized) int;)
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(int_array_1, int* p = new(initialized) int[1];)
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(int_array, int* p = new(initialized) int[10];)
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(string, Array<char>* p = new(initialized) Array<char>();)
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(string_array,
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   Array<char>* p = new(initialized) Array<char>[5];)
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(char_array, char* p = new(initialized) char[5];)
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(appended_string,
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Array<char>* p = new Array<char>();
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p->append(Array<char>());
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles))
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(plain_ptr, int** p = new(initialized) int*;)
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(linking_ptr,
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int** p = new(initialized) int*;
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *p = new(initialized) int;
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles))
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// small objects:
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(0_sized, void* p = malloc(0);)  // 0-sized object (important)
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(1_sized, void* p = malloc(1);)
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(2_sized, void* p = malloc(2);)
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(3_sized, void* p = malloc(3);)
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(4_sized, void* p = malloc(4);)
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int set_data[] = { 1, 2, 3, 4, 5, 6, 7, 21, 22, 23, 24, 25, 26, 27 };
10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static set<int> live_leak_set(set_data, set_data+7);
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const set<int> live_leak_const_set(set_data, set_data+14);
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(set,
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set<int>* p = new(initialized) set<int>(set_data, set_data + 13);
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles))
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ClassA {
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit ClassA(int a) : ptr(NULL) { }
10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mutable char* ptr;
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const ClassA live_leak_mutable(1);
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template<class C>
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TClass {
11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit TClass(int a) : ptr(NULL) { }
11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mutable C val;
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mutable C* ptr;
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const TClass<Array<char> > live_leak_templ_mutable(1);
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ClassB {
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ClassB() { }
11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char b[7];
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void f() { }
11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~ClassB() { }
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ClassB2 {
11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ClassB2() { }
11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char b2[11];
11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void f2() { }
11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~ClassB2() { }
11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ClassD1 : public ClassB {
11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char d1[15];
11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void f() { }
11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ClassD2 : public ClassB2 {
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char d2[19];
11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void f2() { }
11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ClassD : public ClassD1, public ClassD2 {
11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char d[3];
11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void f() { }
11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void f2() { }
11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to test pointers to objects of base subclasses:
11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(B,  ClassB*  p = new(initialized) ClassB;)
11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(D1, ClassD1* p = new(initialized) ClassD1;)
11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(D2, ClassD2* p = new(initialized) ClassD2;)
11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(D,  ClassD*  p = new(initialized) ClassD;)
11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(D1_as_B,  ClassB*  p = new(initialized) ClassD1;)
11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(D2_as_B2, ClassB2* p = new(initialized) ClassD2;)
11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(D_as_B,   ClassB*  p = new(initialized)  ClassD;)
11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(D_as_D1,  ClassD1* p = new(initialized) ClassD;)
11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// inside-object pointers:
11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(D_as_B2,  ClassB2* p = new(initialized) ClassD;)
11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(D_as_D2,  ClassD2* p = new(initialized) ClassD;)
11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class InterfaceA {
11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void A() = 0;
11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~InterfaceA() { }
11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InterfaceA() { }
11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class InterfaceB {
11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void B() = 0;
11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~InterfaceB() { }
11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InterfaceB() { }
11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class InterfaceC : public InterfaceA {
11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void C() = 0;
11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~InterfaceC() { }
11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  InterfaceC() { }
11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ClassMltD1 : public ClassB, public InterfaceB, public InterfaceC {
11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char d1[11];
11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void f() { }
11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void A() { }
11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void B() { }
11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void C() { }
11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ClassMltD2 : public InterfaceA, public InterfaceB, public ClassB {
11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char d2[15];
11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void f() { }
11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void A() { }
11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void B() { }
11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to specifically test heap reachability under
11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// inerface-only multiple inheritance (some use inside-object pointers):
11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(MltD1,       ClassMltD1* p = new(initialized) ClassMltD1;)
11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(MltD1_as_B,  ClassB*     p = new(initialized) ClassMltD1;)
11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(MltD1_as_IA, InterfaceA* p = new(initialized) ClassMltD1;)
12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(MltD1_as_IB, InterfaceB* p = new(initialized) ClassMltD1;)
12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(MltD1_as_IC, InterfaceC* p = new(initialized) ClassMltD1;)
12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(MltD2,       ClassMltD2* p = new(initialized) ClassMltD2;)
12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(MltD2_as_B,  ClassB*     p = new(initialized) ClassMltD2;)
12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(MltD2_as_IA, InterfaceA* p = new(initialized) ClassMltD2;)
12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(MltD2_as_IB, InterfaceB* p = new(initialized) ClassMltD2;)
12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to mimic UnicodeString defined in third_party/icu,
12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// which store a platform-independent-sized refcount in the first
12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// few bytes and keeps a pointer pointing behind the refcount.
12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(unicode_string,
12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char* p = new char[sizeof(uint32) * 10];
12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p += sizeof(uint32);
12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles))
12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// similar, but for platform-dependent-sized refcount
12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(ref_counted,
12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char* p = new char[sizeof(int) * 20];
12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p += sizeof(int);
12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles))
12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct Nesting {
12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct Inner {
12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Nesting* parent;
12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Inner(Nesting* p) : parent(p) {}
12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Inner i0;
12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char n1[5];
12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Inner i1;
12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char n2[11];
12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Inner i2;
12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char n3[27];
12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Inner i3;
12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Nesting() : i0(this), i1(this), i2(this), i3(this) {}
12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to test inside-object pointers pointing at objects nested into heap objects:
12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(nesting_i0, Nesting::Inner* p = &((new Nesting())->i0);)
12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(nesting_i1, Nesting::Inner* p = &((new Nesting())->i1);)
12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(nesting_i2, Nesting::Inner* p = &((new Nesting())->i2);)
12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)REGISTER_OBJ_MAKER(nesting_i3, Nesting::Inner* p = &((new Nesting())->i3);)
12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// allocate many objects reachable from global data
12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void TestHeapLeakCheckerLiveness() {
12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  live_leak_mutable.ptr = new(initialized) char[77];
12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  live_leak_templ_mutable.ptr = new(initialized) Array<char>();
12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  live_leak_templ_mutable.val = Array<char>();
12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestObjMakers();
12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ========================================================================= //
12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Get address (PC value) following the mmap call into addr_after_mmap_call
12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void* Mmapper(uintptr_t* addr_after_mmap_call) {
12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* r = mmap(NULL, 100, PROT_READ|PROT_WRITE,
12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get current PC value into addr_after_mmap_call
12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* stack[1];
12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_EQ(GetStackTrace(stack, 1, 0), 1);
12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *addr_after_mmap_call = reinterpret_cast<uintptr_t>(stack[0]);
12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sleep(0);  // undo -foptimize-sibling-calls
12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return r;
12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to trick complier into preventing inlining
12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void* (*mmapper_addr)(uintptr_t* addr) = &Mmapper;
12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(maxim): copy/move this to memory_region_map_unittest
12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(maxim): expand this test to include mmap64, mremap and sbrk calls.
12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void VerifyMemoryRegionMapStackGet() {
12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uintptr_t caller_addr_limit;
12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* addr = (*mmapper_addr)(&caller_addr_limit);
12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uintptr_t caller = 0;
12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  { MemoryRegionMap::LockHolder l;
12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (MemoryRegionMap::RegionIterator
12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           i = MemoryRegionMap::BeginRegionLocked();
12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           i != MemoryRegionMap::EndRegionLocked(); ++i) {
12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (i->start_addr == reinterpret_cast<uintptr_t>(addr)) {
12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CHECK_EQ(caller, 0);
12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        caller = i->caller();
12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // caller must point into Mmapper function:
12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!(reinterpret_cast<uintptr_t>(mmapper_addr) <= caller  &&
12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        caller < caller_addr_limit)) {
12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOGF << std::hex << "0x" << caller
12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         << " does not seem to point into code of function Mmapper at "
12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         << "0x" << reinterpret_cast<uintptr_t>(mmapper_addr)
12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         << "! Stack frame collection must be off in MemoryRegionMap!";
12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(FATAL, "\n");
12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  munmap(addr, 100);
12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void* Mallocer(uintptr_t* addr_after_malloc_call) {
12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* r = malloc(100);
12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sleep(0);  // undo -foptimize-sibling-calls
12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Get current PC value into addr_after_malloc_call
13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* stack[1];
13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK_EQ(GetStackTrace(stack, 1, 0), 1);
13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *addr_after_malloc_call = reinterpret_cast<uintptr_t>(stack[0]);
13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return r;
13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to trick complier into preventing inlining
13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void* (*mallocer_addr)(uintptr_t* addr) = &Mallocer;
13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// non-static for friendship with HeapProfiler
13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(maxim): expand this test to include
13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// realloc, calloc, memalign, valloc, pvalloc, new, and new[].
13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extern void VerifyHeapProfileTableStackGet() {
13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uintptr_t caller_addr_limit;
13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* addr = (*mallocer_addr)(&caller_addr_limit);
13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uintptr_t caller =
13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    reinterpret_cast<uintptr_t>(HeapLeakChecker::GetAllocCaller(addr));
13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // caller must point into Mallocer function:
13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!(reinterpret_cast<uintptr_t>(mallocer_addr) <= caller  &&
13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        caller < caller_addr_limit)) {
13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOGF << std::hex << "0x" << caller
13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         << " does not seem to point into code of function Mallocer at "
13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         << "0x" << reinterpret_cast<uintptr_t>(mallocer_addr)
13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         << "! Stack frame collection must be off in heap profiler!";
13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(FATAL, "\n");
13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  free(addr);
13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ========================================================================= //
13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void MakeALeak(void** arr) {
13325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PreventHeapReclaiming(10 * sizeof(int));
13335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* a = new(initialized) int[10];
13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Hide(&a);
13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *arr = a;
13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper to do 'return 0;' inside main(): insted we do 'return Pass();'
13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int Pass() {
13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fprintf(stdout, "PASS\n");
13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_have_exited_main = true;
13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return 0;
13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int main(int argc, char** argv) {
13465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  run_hidden_ptr = DoRunHidden;
13475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wipe_stack_ptr = DoWipeStack;
13485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!HeapLeakChecker::IsActive()) {
13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK_EQ(FLAGS_heap_check, "");
13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(WARNING, "HeapLeakChecker got turned off; we won't test much...");
13515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
13525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VerifyMemoryRegionMapStackGet();
13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VerifyHeapProfileTableStackGet();
13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  KeyInit();
13575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // glibc 2.4, on x86_64 at least, has a lock-ordering bug, which
13595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // means deadlock is possible when one thread calls dl_open at the
13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // same time another thread is calling dl_iterate_phdr.  libunwind
13615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // calls dl_iterate_phdr, and TestLibCAllocate calls dl_open (or the
13625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // various syscalls in it do), at least the first time it's run.
13635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // To avoid the deadlock, we run TestLibCAllocate once before getting
13645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // multi-threaded.
13655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(csilvers): once libc is fixed, or libunwind can work around it,
13665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //                 get rid of this early call.  We *want* our test to
13675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //                 find potential problems like this one!
13685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestLibCAllocate();
13695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (FLAGS_interfering_threads) {
13715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RunHeapBusyThreads();  // add interference early
13725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestLibCAllocate();
13745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOGF << "In main(): heap_check=" << FLAGS_heap_check << endl;
13765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(HeapLeakChecker::NoGlobalLeaks());  // so far, so good
13785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (FLAGS_test_leak) {
13805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* arr;
13815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RunHidden(NewCallback(MakeALeak, &arr));
13825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Use(&arr);
13835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogHidden("Leaking", arr);
13845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (FLAGS_test_cancel_global_check) {
13855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      HeapLeakChecker::CancelGlobalCheck();
13865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Verify we can call NoGlobalLeaks repeatedly without deadlocking
13885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      HeapLeakChecker::NoGlobalLeaks();
13895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      HeapLeakChecker::NoGlobalLeaks();
13905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
13915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return Pass();
13925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // whole-program leak-check should (with very high probability)
13935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // catch the leak of arr (10 * sizeof(int) bytes)
13945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // (when !FLAGS_test_cancel_global_check)
13955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (FLAGS_test_loop_leak) {
13985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* arr1;
13995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* arr2;
14005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RunHidden(NewCallback(MakeDeathLoop, &arr1, &arr2));
14015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Use(&arr1);
14025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Use(&arr2);
14035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogHidden("Loop leaking", arr1);
14045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LogHidden("Loop leaking", arr2);
14055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (FLAGS_test_cancel_global_check) {
14065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      HeapLeakChecker::CancelGlobalCheck();
14075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
14085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Verify we can call NoGlobalLeaks repeatedly without deadlocking
14095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      HeapLeakChecker::NoGlobalLeaks();
14105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      HeapLeakChecker::NoGlobalLeaks();
14115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
14125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return Pass();
14135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // whole-program leak-check should (with very high probability)
14145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // catch the leak of arr1 and arr2 (4 * sizeof(void*) bytes)
14155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // (when !FLAGS_test_cancel_global_check)
14165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (FLAGS_test_register_leak) {
14195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // make us fail only where the .sh test expects:
14205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Pause();
14215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i = 0; i < 100; ++i) {  // give it some time to crash
14225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CHECK(HeapLeakChecker::NoGlobalLeaks());
14235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Pause();
14245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
14255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return Pass();
14265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestHeapLeakCheckerLiveness();
14295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HeapLeakChecker heap_check("all");
14315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestHiddenPointer();
14335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestHeapLeakChecker();
14355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Pause();
14365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestLeakButTotalsMatch();
14375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Pause();
14385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestHeapLeakCheckerDeathSimple();
14405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Pause();
14415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestHeapLeakCheckerDeathLoop();
14425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Pause();
14435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestHeapLeakCheckerDeathInverse();
14445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Pause();
14455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestHeapLeakCheckerDeathNoLeaks();
14465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Pause();
14475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestHeapLeakCheckerDeathCountLess();
14485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Pause();
14495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestHeapLeakCheckerDeathCountMore();
14505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Pause();
14515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestHeapLeakCheckerDeathTrick();
14535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Pause();
14545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(HeapLeakChecker::NoGlobalLeaks());  // so far, so good
14565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestHeapLeakCheckerNoFalsePositives();
14585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Pause();
14595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestHeapLeakCheckerDisabling();
14615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Pause();
14625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestSTLAlloc();
14645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Pause();
14655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestSTLAllocInverse();
14665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Pause();
14675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test that various STL allocators work.  Some of these are redundant, but
14695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // we don't know how STL might change in the future.  For example,
14705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // http://wiki/Main/StringNeStdString.
14715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define DTSL(a) { DirectTestSTLAlloc(a, #a); \
14725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  Pause(); }
14735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DTSL(std::allocator<char>());
14745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DTSL(std::allocator<int>());
14755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DTSL(std::string().get_allocator());
14765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DTSL(string().get_allocator());
14775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DTSL(vector<int>().get_allocator());
14785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DTSL(vector<double>().get_allocator());
14795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DTSL(vector<vector<int> >().get_allocator());
14805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DTSL(vector<string>().get_allocator());
14815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DTSL((map<string, string>().get_allocator()));
14825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DTSL((map<string, int>().get_allocator()));
14835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DTSL(set<char>().get_allocator());
14845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef DTSL
14855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TestLibCAllocate();
14875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Pause();
14885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(HeapLeakChecker::NoGlobalLeaks());  // so far, so good
14905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Pause();
14925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!FLAGS_maybe_stripped) {
14945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(heap_check.SameHeap());
14955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
14965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WARN_IF(heap_check.SameHeap() != true,
14975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            "overall leaks are caught; we must be using a stripped binary");
14985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(HeapLeakChecker::NoGlobalLeaks());  // so far, so good
15015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Pass();
15035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1504