- add sources.
[platform/framework/web/crosswalk.git] / src / third_party / tcmalloc / vendor / src / debugallocation.cc
1 // Copyright (c) 2000, Google Inc.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 //     * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 //     * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
13 // distribution.
14 //     * Neither the name of Google Inc. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30 // ---
31 // Author: Urs Holzle <opensource@google.com>
32
33 #include "config.h"
34 #include <errno.h>
35 #ifdef HAVE_FCNTL_H
36 #include <fcntl.h>
37 #endif
38 #ifdef HAVE_INTTYPES_H
39 #include <inttypes.h>
40 #endif
41 // We only need malloc.h for struct mallinfo.
42 #ifdef HAVE_STRUCT_MALLINFO
43 // Malloc can be in several places on older versions of OS X.
44 # if defined(HAVE_MALLOC_H)
45 # include <malloc.h>
46 # elif defined(HAVE_MALLOC_MALLOC_H)
47 # include <malloc/malloc.h>
48 # elif defined(HAVE_SYS_MALLOC_H)
49 # include <sys/malloc.h>
50 # endif
51 #endif
52 #ifdef HAVE_PTHREAD
53 #include <pthread.h>
54 #endif
55 #include <stdarg.h>
56 #include <stdio.h>
57 #include <string.h>
58 #ifdef HAVE_MMAP
59 #include <sys/mman.h>
60 #endif
61 #include <sys/stat.h>
62 #include <sys/types.h>
63 #ifdef HAVE_UNISTD_H
64 #include <unistd.h>
65 #endif
66
67 #include <gperftools/malloc_extension.h>
68 #include <gperftools/malloc_hook.h>
69 #include <gperftools/stacktrace.h>
70 #include "addressmap-inl.h"
71 #include "base/commandlineflags.h"
72 #include "base/googleinit.h"
73 #include "base/logging.h"
74 #include "base/spinlock.h"
75 #include "malloc_hook-inl.h"
76 #include "symbolize.h"
77
78 #define TCMALLOC_USING_DEBUGALLOCATION
79 #include "tcmalloc.cc"
80
81 // __THROW is defined in glibc systems.  It means, counter-intuitively,
82 // "This function will never throw an exception."  It's an optional
83 // optimization tool, but we may need to use it to match glibc prototypes.
84 #ifndef __THROW    // I guess we're not on a glibc system
85 # define __THROW   // __THROW is just an optimization, so ok to make it ""
86 #endif
87
88 // On systems (like freebsd) that don't define MAP_ANONYMOUS, use the old
89 // form of the name instead.
90 #ifndef MAP_ANONYMOUS
91 # define MAP_ANONYMOUS MAP_ANON
92 #endif
93
94 // ========================================================================= //
95
96 DEFINE_bool(malloctrace,
97             EnvToBool("TCMALLOC_TRACE", false),
98             "Enables memory (de)allocation tracing to /tmp/google.alloc.");
99 #ifdef HAVE_MMAP
100 DEFINE_bool(malloc_page_fence,
101             EnvToBool("TCMALLOC_PAGE_FENCE", false),
102             "Enables putting of memory allocations at page boundaries "
103             "with a guard page following the allocation (to catch buffer "
104             "overruns right when they happen).");
105 DEFINE_bool(malloc_page_fence_never_reclaim,
106             EnvToBool("TCMALLOC_PAGE_FRANCE_NEVER_RECLAIM", false),
107             "Enables making the virtual address space inaccessible "
108             "upon a deallocation instead of returning it and reusing later.");
109 #else
110 DEFINE_bool(malloc_page_fence, false, "Not usable (requires mmap)");
111 DEFINE_bool(malloc_page_fence_never_reclaim, false, "Not usable (required mmap)");
112 #endif
113 DEFINE_bool(malloc_reclaim_memory,
114             EnvToBool("TCMALLOC_RECLAIM_MEMORY", true),
115             "If set to false, we never return memory to malloc "
116             "when an object is deallocated. This ensures that all "
117             "heap object addresses are unique.");
118 DEFINE_int32(max_free_queue_size,
119              EnvToInt("TCMALLOC_MAX_FREE_QUEUE_SIZE", 10*1024*1024),
120              "If greater than 0, keep freed blocks in a queue instead of "
121              "releasing them to the allocator immediately.  Release them when "
122              "the total size of all blocks in the queue would otherwise exceed "
123              "this limit.");
124
125 DEFINE_bool(symbolize_stacktrace,
126             EnvToBool("TCMALLOC_SYMBOLIZE_STACKTRACE", true),
127             "Symbolize the stack trace when provided (on some error exits)");
128
129 // If we are LD_PRELOAD-ed against a non-pthreads app, then
130 // pthread_once won't be defined.  We declare it here, for that
131 // case (with weak linkage) which will cause the non-definition to
132 // resolve to NULL.  We can then check for NULL or not in Instance.
133 extern "C" int pthread_once(pthread_once_t *, void (*)(void))
134     ATTRIBUTE_WEAK;
135
136 // ========================================================================= //
137
138 // A safe version of printf() that does not do any allocation and
139 // uses very little stack space.
140 static void TracePrintf(int fd, const char *fmt, ...)
141   __attribute__ ((__format__ (__printf__, 2, 3)));
142
143 // The do_* functions are defined in tcmalloc/tcmalloc.cc,
144 // which is included before this file
145 // when TCMALLOC_FOR_DEBUGALLOCATION is defined
146 // TODO(csilvers): get rid of these now that we are tied to tcmalloc.
147 #define BASE_MALLOC_NEW    do_malloc
148 #define BASE_MALLOC        do_malloc
149 #define BASE_FREE          do_free
150 #define BASE_MALLOC_STATS  do_malloc_stats
151 #define BASE_MALLOPT       do_mallopt
152 #define BASE_MALLINFO      do_mallinfo
153
154 // ========================================================================= //
155
156 class MallocBlock;
157
158 // A circular buffer to hold freed blocks of memory.  MallocBlock::Deallocate
159 // (below) pushes blocks into this queue instead of returning them to the
160 // underlying allocator immediately.  See MallocBlock::Deallocate for more
161 // information.
162 //
163 // We can't use an STL class for this because we need to be careful not to
164 // perform any heap de-allocations in any of the code in this class, since the
165 // code in MallocBlock::Deallocate is not re-entrant.
166 template <typename QueueEntry>
167 class FreeQueue {
168  public:
169   FreeQueue() : q_front_(0), q_back_(0) {}
170
171   bool Full() {
172     return (q_front_ + 1) % kFreeQueueSize == q_back_;
173   }
174
175   void Push(const QueueEntry& block) {
176     q_[q_front_] = block;
177     q_front_ = (q_front_ + 1) % kFreeQueueSize;
178   }
179
180   QueueEntry Pop() {
181     RAW_CHECK(q_back_ != q_front_, "Queue is empty");
182     const QueueEntry& ret = q_[q_back_];
183     q_back_ = (q_back_ + 1) % kFreeQueueSize;
184     return ret;
185   }
186
187   size_t size() const {
188     return (q_front_ - q_back_ + kFreeQueueSize) % kFreeQueueSize;
189   }
190
191  private:
192   // Maximum number of blocks kept in the free queue before being freed.
193   static const int kFreeQueueSize = 1024;
194
195   QueueEntry q_[kFreeQueueSize];
196   int q_front_;
197   int q_back_;
198 };
199
200 struct MallocBlockQueueEntry {
201   MallocBlockQueueEntry() : block(NULL), size(0),
202                             num_deleter_pcs(0), deleter_threadid(0) {}
203   MallocBlockQueueEntry(MallocBlock* b, size_t s) : block(b), size(s) {
204     if (FLAGS_max_free_queue_size != 0 && b != NULL) {
205       // Adjust the number of frames to skip (4) if you change the
206       // location of this call.
207       num_deleter_pcs =
208           GetStackTrace(deleter_pcs,
209                         sizeof(deleter_pcs) / sizeof(deleter_pcs[0]),
210                         4);
211       deleter_threadid = pthread_self();
212     } else {
213       num_deleter_pcs = 0;
214       // Zero is an illegal pthread id by my reading of the pthread
215       // implementation:
216       deleter_threadid = 0;
217     }
218   }
219
220   MallocBlock* block;
221   size_t size;
222
223   // When deleted and put in the free queue, we (flag-controlled)
224   // record the stack so that if corruption is later found, we can
225   // print the deleter's stack.  (These three vars add 144 bytes of
226   // overhead under the LP64 data model.)
227   void* deleter_pcs[16];
228   int num_deleter_pcs;
229   pthread_t deleter_threadid;
230 };
231
232 class MallocBlock {
233  public:  // allocation type constants
234
235   // Different allocation types we distinguish.
236   // Note: The lower 4 bits are not random: we index kAllocName array
237   // by these values masked with kAllocTypeMask;
238   // the rest are "random" magic bits to help catch memory corruption.
239   static const int kMallocType = 0xEFCDAB90;
240   static const int kNewType = 0xFEBADC81;
241   static const int kArrayNewType = 0xBCEADF72;
242
243  private:  // constants
244
245   // A mask used on alloc types above to get to 0, 1, 2
246   static const int kAllocTypeMask = 0x3;
247   // An additional bit to set in AllocType constants
248   // to mark now deallocated regions.
249   static const int kDeallocatedTypeBit = 0x4;
250
251   // For better memory debugging, we initialize all storage to known
252   // values, and overwrite the storage when it's deallocated:
253   // Byte that fills uninitialized storage.
254   static const int kMagicUninitializedByte = 0xAB;
255   // Byte that fills deallocated storage.
256   // NOTE: tcmalloc.cc depends on the value of kMagicDeletedByte
257   //       to work around a bug in the pthread library.
258   static const int kMagicDeletedByte = 0xCD;
259   // A size_t (type of alloc_type_ below) in a deallocated storage
260   // filled with kMagicDeletedByte.
261   static const size_t kMagicDeletedSizeT =
262       0xCDCDCDCD | (((size_t)0xCDCDCDCD << 16) << 16);
263     // Initializer works for 32 and 64 bit size_ts;
264     // "<< 16 << 16" is to fool gcc from issuing a warning
265     // when size_ts are 32 bits.
266
267   // NOTE: on Linux, you can enable malloc debugging support in libc by
268   // setting the environment variable MALLOC_CHECK_ to 1 before you
269   // start the program (see man malloc).
270
271   // We use either BASE_MALLOC or mmap to make the actual allocation. In
272   // order to remember which one of the two was used for any block, we store an
273   // appropriate magic word next to the block.
274   static const int kMagicMalloc = 0xDEADBEEF;
275   static const int kMagicMMap = 0xABCDEFAB;
276
277   // This array will be filled with 0xCD, for use with memcmp.
278   static unsigned char kMagicDeletedBuffer[1024];
279   static pthread_once_t deleted_buffer_initialized_;
280   static bool deleted_buffer_initialized_no_pthreads_;
281
282  private:  // data layout
283
284                     // The four fields size1_,offset_,magic1_,alloc_type_
285                     // should together occupy a multiple of 16 bytes. (At the
286                     // moment, sizeof(size_t) == 4 or 8 depending on piii vs
287                     // k8, and 4 of those sum to 16 or 32 bytes).
288                     // This, combined with BASE_MALLOC's alignment guarantees,
289                     // ensures that SSE types can be stored into the returned
290                     // block, at &size2_.
291   size_t size1_;
292   size_t offset_;   // normally 0 unless memaligned memory
293                     // see comments in memalign() and FromRawPointer().
294   size_t magic1_;
295   size_t alloc_type_;
296   // here comes the actual data (variable length)
297   // ...
298   // then come the size2_ and magic2_, or a full page of mprotect-ed memory
299   // if the malloc_page_fence feature is enabled.
300   size_t size2_;
301   int magic2_;
302
303  private:  // static data and helpers
304
305   // Allocation map: stores the allocation type for each allocated object,
306   // or the type or'ed with kDeallocatedTypeBit
307   // for each formerly allocated object.
308   typedef AddressMap<int> AllocMap;
309   static AllocMap* alloc_map_;
310   // This protects alloc_map_ and consistent state of metadata
311   // for each still-allocated object in it.
312   // We use spin locks instead of pthread_mutex_t locks
313   // to prevent crashes via calls to pthread_mutex_(un)lock
314   // for the (de)allocations coming from pthreads initialization itself.
315   static SpinLock alloc_map_lock_;
316
317   // A queue of freed blocks.  Instead of releasing blocks to the allocator
318   // immediately, we put them in a queue, freeing them only when necessary
319   // to keep the total size of all the freed blocks below the limit set by
320   // FLAGS_max_free_queue_size.
321   static FreeQueue<MallocBlockQueueEntry>* free_queue_;
322
323   static size_t free_queue_size_;  // total size of blocks in free_queue_
324   // protects free_queue_ and free_queue_size_
325   static SpinLock free_queue_lock_;
326
327   // Names of allocation types (kMallocType, kNewType, kArrayNewType)
328   static const char* const kAllocName[];
329   // Names of corresponding deallocation types
330   static const char* const kDeallocName[];
331
332   static const char* AllocName(int type) {
333     return kAllocName[type & kAllocTypeMask];
334   }
335
336   static const char* DeallocName(int type) {
337     return kDeallocName[type & kAllocTypeMask];
338   }
339
340  private:  // helper accessors
341
342   bool IsMMapped() const { return kMagicMMap == magic1_; }
343
344   bool IsValidMagicValue(int value) const {
345     return kMagicMMap == value  ||  kMagicMalloc == value;
346   }
347
348   static size_t real_malloced_size(size_t size) {
349     return size + sizeof(MallocBlock);
350   }
351   static size_t real_mmapped_size(size_t size) {
352     return size + MallocBlock::data_offset();
353   }
354
355   size_t real_size() {
356     return IsMMapped() ? real_mmapped_size(size1_) : real_malloced_size(size1_);
357   }
358
359   // NOTE: if the block is mmapped (that is, we're using the
360   // malloc_page_fence option) then there's no size2 or magic2
361   // (instead, the guard page begins where size2 would be).
362
363   size_t* size2_addr() { return (size_t*)((char*)&size2_ + size1_); }
364   const size_t* size2_addr() const {
365     return (const size_t*)((char*)&size2_ + size1_);
366   }
367
368   int* magic2_addr() { return (int*)(size2_addr() + 1); }
369   const int* magic2_addr() const { return (const int*)(size2_addr() + 1); }
370
371  private:  // other helpers
372
373   void Initialize(size_t size, int type) {
374     RAW_CHECK(IsValidMagicValue(magic1_), "");
375     // record us as allocated in the map
376     alloc_map_lock_.Lock();
377     if (!alloc_map_) {
378       void* p = BASE_MALLOC(sizeof(AllocMap));
379       alloc_map_ = new(p) AllocMap(BASE_MALLOC, BASE_FREE);
380     }
381     alloc_map_->Insert(data_addr(), type);
382     // initialize us
383     size1_ = size;
384     offset_ = 0;
385     alloc_type_ = type;
386     if (!IsMMapped()) {
387       *magic2_addr() = magic1_;
388       *size2_addr() = size;
389     }
390     alloc_map_lock_.Unlock();
391     memset(data_addr(), kMagicUninitializedByte, size);
392     if (!IsMMapped()) {
393       RAW_CHECK(size1_ == *size2_addr(), "should hold");
394       RAW_CHECK(magic1_ == *magic2_addr(), "should hold");
395     }
396   }
397
398   size_t CheckAndClear(int type) {
399     alloc_map_lock_.Lock();
400     CheckLocked(type);
401     if (!IsMMapped()) {
402       RAW_CHECK(size1_ == *size2_addr(), "should hold");
403     }
404     // record us as deallocated in the map
405     alloc_map_->Insert(data_addr(), type | kDeallocatedTypeBit);
406     alloc_map_lock_.Unlock();
407     // clear us
408     const size_t size = real_size();
409     memset(this, kMagicDeletedByte, size);
410     return size;
411   }
412
413   void CheckLocked(int type) const {
414     int map_type = 0;
415     const int* found_type =
416       alloc_map_ != NULL ? alloc_map_->Find(data_addr()) : NULL;
417     if (found_type == NULL) {
418       RAW_LOG(FATAL, "memory allocation bug: object at %p "
419                      "has never been allocated", data_addr());
420     } else {
421       map_type = *found_type;
422     }
423     if ((map_type & kDeallocatedTypeBit) != 0) {
424       RAW_LOG(FATAL, "memory allocation bug: object at %p "
425                      "has been already deallocated (it was allocated with %s)",
426                      data_addr(), AllocName(map_type & ~kDeallocatedTypeBit));
427     }
428     if (alloc_type_ == kMagicDeletedSizeT) {
429       RAW_LOG(FATAL, "memory stomping bug: a word before object at %p "
430                      "has been corrupted; or else the object has been already "
431                      "deallocated and our memory map has been corrupted",
432                      data_addr());
433     }
434     if (!IsValidMagicValue(magic1_)) {
435       RAW_LOG(FATAL, "memory stomping bug: a word before object at %p "
436                      "has been corrupted; "
437                      "or else our memory map has been corrupted and this is a "
438                      "deallocation for not (currently) heap-allocated object",
439                      data_addr());
440     }
441     if (!IsMMapped()) {
442       if (size1_ != *size2_addr()) {
443         RAW_LOG(FATAL, "memory stomping bug: a word after object at %p "
444                        "has been corrupted", data_addr());
445       }
446       if (!IsValidMagicValue(*magic2_addr())) {
447         RAW_LOG(FATAL, "memory stomping bug: a word after object at %p "
448                 "has been corrupted", data_addr());
449       }
450     }
451     if (alloc_type_ != type) {
452       if ((alloc_type_ != MallocBlock::kMallocType) &&
453           (alloc_type_ != MallocBlock::kNewType)    &&
454           (alloc_type_ != MallocBlock::kArrayNewType)) {
455         RAW_LOG(FATAL, "memory stomping bug: a word before object at %p "
456                        "has been corrupted", data_addr());
457       }
458       RAW_LOG(FATAL, "memory allocation/deallocation mismatch at %p: "
459                      "allocated with %s being deallocated with %s",
460                      data_addr(), AllocName(alloc_type_), DeallocName(type));
461     }
462     if (alloc_type_ != map_type) {
463       RAW_LOG(FATAL, "memory stomping bug: our memory map has been corrupted : "
464                      "allocation at %p made with %s "
465                      "is recorded in the map to be made with %s",
466                      data_addr(), AllocName(alloc_type_),  AllocName(map_type));
467     }
468   }
469
470  public:  // public accessors
471
472   void* data_addr() { return (void*)&size2_; }
473   const void* data_addr() const { return (const void*)&size2_; }
474
475   static size_t data_offset() { return OFFSETOF_MEMBER(MallocBlock, size2_); }
476
477   size_t data_size() const { return size1_; }
478
479   void set_offset(int offset) { this->offset_ = offset; }
480
481  public:  // our main interface
482
483   static MallocBlock* Allocate(size_t size, int type) {
484     // Prevent an integer overflow / crash with large allocation sizes.
485     // TODO - Note that for a e.g. 64-bit size_t, max_size_t may not actually
486     // be the maximum value, depending on how the compiler treats ~0. The worst
487     // practical effect is that allocations are limited to 4Gb or so, even if
488     // the address space could take more.
489     static size_t max_size_t = ~0;
490     if (size > max_size_t - sizeof(MallocBlock)) {
491       RAW_LOG(ERROR, "Massive size passed to malloc: %"PRIuS"", size);
492       return NULL;
493     }
494     MallocBlock* b = NULL;
495     const bool use_malloc_page_fence = FLAGS_malloc_page_fence;
496 #ifdef HAVE_MMAP
497     if (use_malloc_page_fence) {
498       // Put the block towards the end of the page and make the next page
499       // inaccessible. This will catch buffer overrun right when it happens.
500       size_t sz = real_mmapped_size(size);
501       int pagesize = getpagesize();
502       int num_pages = (sz + pagesize - 1) / pagesize + 1;
503       char* p = (char*) mmap(NULL, num_pages * pagesize, PROT_READ|PROT_WRITE,
504                              MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
505       if (p == MAP_FAILED) {
506         // If the allocation fails, abort rather than returning NULL to
507         // malloc. This is because in most cases, the program will run out
508         // of memory in this mode due to tremendous amount of wastage. There
509         // is no point in propagating the error elsewhere.
510         RAW_LOG(FATAL, "Out of memory: possibly due to page fence overhead: %s",
511                 strerror(errno));
512       }
513       // Mark the page after the block inaccessible
514       if (mprotect(p + (num_pages - 1) * pagesize, pagesize, PROT_NONE)) {
515         RAW_LOG(FATAL, "Guard page setup failed: %s", strerror(errno));
516       }
517       b = (MallocBlock*) (p + (num_pages - 1) * pagesize - sz);
518     } else {
519       b = (MallocBlock*) (type == kMallocType ?
520                           BASE_MALLOC(real_malloced_size(size)) :
521                           BASE_MALLOC_NEW(real_malloced_size(size)));
522     }
523 #else
524     b = (MallocBlock*) (type == kMallocType ?
525                         BASE_MALLOC(real_malloced_size(size)) :
526                         BASE_MALLOC_NEW(real_malloced_size(size)));
527 #endif
528
529     // It would be nice to output a diagnostic on allocation failure
530     // here, but logging (other than FATAL) requires allocating
531     // memory, which could trigger a nasty recursion. Instead, preserve
532     // malloc semantics and return NULL on failure.
533     if (b != NULL) {
534       b->magic1_ = use_malloc_page_fence ? kMagicMMap : kMagicMalloc;
535       b->Initialize(size, type);
536     }
537     return b;
538   }
539
540   void Deallocate(int type) {
541     if (IsMMapped()) {  // have to do this before CheckAndClear
542 #ifdef HAVE_MMAP
543       int size = CheckAndClear(type);
544       int pagesize = getpagesize();
545       int num_pages = (size + pagesize - 1) / pagesize + 1;
546       char* p = (char*) this;
547       if (FLAGS_malloc_page_fence_never_reclaim  ||
548           !FLAGS_malloc_reclaim_memory) {
549         mprotect(p - (num_pages - 1) * pagesize + size,
550                  num_pages * pagesize, PROT_NONE);
551       } else {
552         munmap(p - (num_pages - 1) * pagesize + size, num_pages * pagesize);
553       }
554 #endif
555     } else {
556       const size_t size = CheckAndClear(type);
557       if (FLAGS_malloc_reclaim_memory) {
558         // Instead of freeing the block immediately, push it onto a queue of
559         // recently freed blocks.  Free only enough blocks to keep from
560         // exceeding the capacity of the queue or causing the total amount of
561         // un-released memory in the queue from exceeding
562         // FLAGS_max_free_queue_size.
563         ProcessFreeQueue(this, size, FLAGS_max_free_queue_size);
564       }
565     }
566   }
567
568   static size_t FreeQueueSize() {
569     SpinLockHolder l(&free_queue_lock_);
570     return free_queue_size_;
571   }
572
573   static void ProcessFreeQueue(MallocBlock* b, size_t size,
574                                int max_free_queue_size) {
575     // MallocBlockQueueEntry are about 144 in size, so we can only
576     // use a small array of them on the stack.
577     MallocBlockQueueEntry entries[4];
578     int num_entries = 0;
579     MallocBlockQueueEntry new_entry(b, size);
580     free_queue_lock_.Lock();
581     if (free_queue_ == NULL)
582       free_queue_ = new FreeQueue<MallocBlockQueueEntry>;
583     RAW_CHECK(!free_queue_->Full(), "Free queue mustn't be full!");
584
585     if (b != NULL) {
586       free_queue_size_ += size + sizeof(MallocBlockQueueEntry);
587       free_queue_->Push(new_entry);
588     }
589
590     // Free blocks until the total size of unfreed blocks no longer exceeds
591     // max_free_queue_size, and the free queue has at least one free
592     // space in it.
593     while (free_queue_size_ > max_free_queue_size || free_queue_->Full()) {
594       RAW_CHECK(num_entries < arraysize(entries), "entries array overflow");
595       entries[num_entries] = free_queue_->Pop();
596       free_queue_size_ -=
597           entries[num_entries].size + sizeof(MallocBlockQueueEntry);
598       num_entries++;
599       if (num_entries == arraysize(entries)) {
600         // The queue will not be full at this point, so it is ok to
601         // release the lock.  The queue may still contain more than
602         // max_free_queue_size, but this is not a strict invariant.
603         free_queue_lock_.Unlock();
604         for (int i = 0; i < num_entries; i++) {
605           CheckForDanglingWrites(entries[i]);
606           BASE_FREE(entries[i].block);
607         }
608         num_entries = 0;
609         free_queue_lock_.Lock();
610       }
611     }
612     RAW_CHECK(free_queue_size_ >= 0, "Free queue size went negative!");
613     free_queue_lock_.Unlock();
614     for (int i = 0; i < num_entries; i++) {
615       CheckForDanglingWrites(entries[i]);
616       BASE_FREE(entries[i].block);
617     }
618   }
619
620   static void InitDeletedBuffer() {
621     memset(kMagicDeletedBuffer, kMagicDeletedByte, sizeof(kMagicDeletedBuffer));
622     deleted_buffer_initialized_no_pthreads_ = true;
623   }
624
625   static void CheckForDanglingWrites(const MallocBlockQueueEntry& queue_entry) {
626     // Initialize the buffer if necessary.
627     if (pthread_once)
628       pthread_once(&deleted_buffer_initialized_, &InitDeletedBuffer);
629     if (!deleted_buffer_initialized_no_pthreads_) {
630       // This will be the case on systems that don't link in pthreads,
631       // including on FreeBSD where pthread_once has a non-zero address
632       // (but doesn't do anything) even when pthreads isn't linked in.
633       InitDeletedBuffer();
634     }
635
636     const unsigned char* p =
637         reinterpret_cast<unsigned char*>(queue_entry.block);
638
639     static const size_t size_of_buffer = sizeof(kMagicDeletedBuffer);
640     const size_t size = queue_entry.size;
641     const size_t buffers = size / size_of_buffer;
642     const size_t remainder = size % size_of_buffer;
643     size_t buffer_idx;
644     for (buffer_idx = 0; buffer_idx < buffers; ++buffer_idx) {
645       CheckForCorruptedBuffer(queue_entry, buffer_idx, p, size_of_buffer);
646       p += size_of_buffer;
647     }
648     CheckForCorruptedBuffer(queue_entry, buffer_idx, p, remainder);
649   }
650
651   static void CheckForCorruptedBuffer(const MallocBlockQueueEntry& queue_entry,
652                                       size_t buffer_idx,
653                                       const unsigned char* buffer,
654                                       size_t size_of_buffer) {
655     if (memcmp(buffer, kMagicDeletedBuffer, size_of_buffer) == 0) {
656       return;
657     }
658
659     RAW_LOG(ERROR,
660             "Found a corrupted memory buffer in MallocBlock (may be offset "
661             "from user ptr): buffer index: %zd, buffer ptr: %p, size of "
662             "buffer: %zd", buffer_idx, buffer, size_of_buffer);
663
664     // The magic deleted buffer should only be 1024 bytes, but in case
665     // this changes, let's put an upper limit on the number of debug
666     // lines we'll output:
667     if (size_of_buffer <= 1024) {
668       for (int i = 0; i < size_of_buffer; ++i) {
669         if (buffer[i] != kMagicDeletedByte) {
670           RAW_LOG(ERROR, "Buffer byte %d is 0x%02x (should be 0x%02x).",
671                   i, buffer[i], kMagicDeletedByte);
672         }
673       }
674     } else {
675       RAW_LOG(ERROR, "Buffer too large to print corruption.");
676     }
677
678     const MallocBlock* b = queue_entry.block;
679     const size_t size = queue_entry.size;
680     if (queue_entry.num_deleter_pcs > 0) {
681       TracePrintf(STDERR_FILENO, "Deleted by thread %p\n",
682                   reinterpret_cast<void*>(
683                       PRINTABLE_PTHREAD(queue_entry.deleter_threadid)));
684
685       // We don't want to allocate or deallocate memory here, so we use
686       // placement-new.  It's ok that we don't destroy this, since we're
687       // just going to error-exit below anyway.  Union is for alignment.
688       union { void* alignment; char buf[sizeof(SymbolTable)]; } tablebuf;
689       SymbolTable* symbolization_table = new (tablebuf.buf) SymbolTable;
690       for (int i = 0; i < queue_entry.num_deleter_pcs; i++) {
691         // Symbolizes the previous address of pc because pc may be in the
692         // next function.  This may happen when the function ends with
693         // a call to a function annotated noreturn (e.g. CHECK).
694         char *pc = reinterpret_cast<char*>(queue_entry.deleter_pcs[i]);
695         symbolization_table->Add(pc - 1);
696       }
697       if (FLAGS_symbolize_stacktrace)
698         symbolization_table->Symbolize();
699       for (int i = 0; i < queue_entry.num_deleter_pcs; i++) {
700         char *pc = reinterpret_cast<char*>(queue_entry.deleter_pcs[i]);
701         TracePrintf(STDERR_FILENO, "    @ %p %s\n",
702                     pc, symbolization_table->GetSymbol(pc - 1));
703       }
704     } else {
705       RAW_LOG(ERROR,
706               "Skipping the printing of the deleter's stack!  Its stack was "
707               "not found; either the corruption occurred too early in "
708               "execution to obtain a stack trace or --max_free_queue_size was "
709               "set to 0.");
710     }
711
712     RAW_LOG(FATAL,
713             "Memory was written to after being freed.  MallocBlock: %p, user "
714             "ptr: %p, size: %zd.  If you can't find the source of the error, "
715             "try using ASan (http://code.google.com/p/address-sanitizer/), "
716             "Valgrind, or Purify, or study the "
717             "output of the deleter's stack printed above.",
718             b, b->data_addr(), size);
719   }
720
721   static MallocBlock* FromRawPointer(void* p) {
722     const size_t data_offset = MallocBlock::data_offset();
723     // Find the header just before client's memory.
724     MallocBlock *mb = reinterpret_cast<MallocBlock *>(
725                 reinterpret_cast<char *>(p) - data_offset);
726     // If mb->alloc_type_ is kMagicDeletedSizeT, we're not an ok pointer.
727     if (mb->alloc_type_ == kMagicDeletedSizeT) {
728       RAW_LOG(FATAL, "memory allocation bug: object at %p has been already"
729                      " deallocated; or else a word before the object has been"
730                      " corrupted (memory stomping bug)", p);
731     }
732     // If mb->offset_ is zero (common case), mb is the real header.  If
733     // mb->offset_ is non-zero, this block was allocated by memalign, and
734     // mb->offset_ is the distance backwards to the real header from mb,
735     // which is a fake header.  The following subtraction works for both zero
736     // and non-zero values.
737     return reinterpret_cast<MallocBlock *>(
738                 reinterpret_cast<char *>(mb) - mb->offset_);
739   }
740   static const MallocBlock* FromRawPointer(const void* p) {
741     // const-safe version: we just cast about
742     return FromRawPointer(const_cast<void*>(p));
743   }
744
745   void Check(int type) const {
746     alloc_map_lock_.Lock();
747     CheckLocked(type);
748     alloc_map_lock_.Unlock();
749   }
750
751   static bool CheckEverything() {
752     alloc_map_lock_.Lock();
753     if (alloc_map_ != NULL)  alloc_map_->Iterate(CheckCallback, 0);
754     alloc_map_lock_.Unlock();
755     return true;  // if we get here, we're okay
756   }
757
758   static bool MemoryStats(int* blocks, size_t* total,
759                           int histogram[kMallocHistogramSize]) {
760     memset(histogram, 0, kMallocHistogramSize * sizeof(int));
761     alloc_map_lock_.Lock();
762     stats_blocks_ = 0;
763     stats_total_ = 0;
764     stats_histogram_ = histogram;
765     if (alloc_map_ != NULL) alloc_map_->Iterate(StatsCallback, 0);
766     *blocks = stats_blocks_;
767     *total = stats_total_;
768     alloc_map_lock_.Unlock();
769     return true;
770   }
771
772  private:  // helpers for CheckEverything and MemoryStats
773
774   static void CheckCallback(const void* ptr, int* type, int dummy) {
775     if ((*type & kDeallocatedTypeBit) == 0) {
776       FromRawPointer(ptr)->CheckLocked(*type);
777     }
778   }
779
780   // Accumulation variables for StatsCallback protected by alloc_map_lock_
781   static int stats_blocks_;
782   static size_t stats_total_;
783   static int* stats_histogram_;
784
785   static void StatsCallback(const void* ptr, int* type, int dummy) {
786     if ((*type & kDeallocatedTypeBit) == 0) {
787       const MallocBlock* b = FromRawPointer(ptr);
788       b->CheckLocked(*type);
789       ++stats_blocks_;
790       size_t mysize = b->size1_;
791       int entry = 0;
792       stats_total_ += mysize;
793       while (mysize) {
794         ++entry;
795         mysize >>= 1;
796       }
797       RAW_CHECK(entry < kMallocHistogramSize,
798                 "kMallocHistogramSize should be at least as large as log2 "
799                 "of the maximum process memory size");
800       stats_histogram_[entry] += 1;
801     }
802   }
803 };
804
805 void DanglingWriteChecker() {
806   // Clear out the remaining free queue to check for dangling writes.
807   MallocBlock::ProcessFreeQueue(NULL, 0, 0);
808 }
809
810 // ========================================================================= //
811
812 const int MallocBlock::kMagicMalloc;
813 const int MallocBlock::kMagicMMap;
814
815 MallocBlock::AllocMap* MallocBlock::alloc_map_ = NULL;
816 SpinLock MallocBlock::alloc_map_lock_(SpinLock::LINKER_INITIALIZED);
817
818 FreeQueue<MallocBlockQueueEntry>* MallocBlock::free_queue_ = NULL;
819 size_t MallocBlock::free_queue_size_ = 0;
820 SpinLock MallocBlock::free_queue_lock_(SpinLock::LINKER_INITIALIZED);
821
822 unsigned char MallocBlock::kMagicDeletedBuffer[1024];
823 pthread_once_t MallocBlock::deleted_buffer_initialized_ = PTHREAD_ONCE_INIT;
824 bool MallocBlock::deleted_buffer_initialized_no_pthreads_ = false;
825
826 const char* const MallocBlock::kAllocName[] = {
827   "malloc",
828   "new",
829   "new []",
830   NULL,
831 };
832
833 const char* const MallocBlock::kDeallocName[] = {
834   "free",
835   "delete",
836   "delete []",
837   NULL,
838 };
839
840 int MallocBlock::stats_blocks_;
841 size_t MallocBlock::stats_total_;
842 int* MallocBlock::stats_histogram_;
843
844 // ========================================================================= //
845
846 // The following cut-down version of printf() avoids
847 // using stdio or ostreams.
848 // This is to guarantee no recursive calls into
849 // the allocator and to bound the stack space consumed.  (The pthread
850 // manager thread in linuxthreads has a very small stack,
851 // so fprintf can't be called.)
852 static void TracePrintf(int fd, const char *fmt, ...) {
853   char buf[64];
854   int i = 0;
855   va_list ap;
856   va_start(ap, fmt);
857   const char *p = fmt;
858   char numbuf[25];
859   numbuf[sizeof(numbuf)-1] = 0;
860   while (*p != '\0') {              // until end of format string
861     char *s = &numbuf[sizeof(numbuf)-1];
862     if (p[0] == '%' && p[1] != 0) {  // handle % formats
863       int64 l = 0;
864       unsigned long base = 0;
865       if (*++p == 's') {                            // %s
866         s = va_arg(ap, char *);
867       } else if (*p == 'l' && p[1] == 'd') {        // %ld
868         l = va_arg(ap, long);
869         base = 10;
870         p++;
871       } else if (*p == 'l' && p[1] == 'u') {        // %lu
872         l = va_arg(ap, unsigned long);
873         base = 10;
874         p++;
875       } else if (*p == 'z' && p[1] == 'u') {        // %zu
876         l = va_arg(ap, size_t);
877         base = 10;
878         p++;
879       } else if (*p == 'u') {                       // %u
880         l = va_arg(ap, unsigned int);
881         base = 10;
882       } else if (*p == 'd') {                       // %d
883         l = va_arg(ap, int);
884         base = 10;
885       } else if (*p == 'p') {                       // %p
886         l = va_arg(ap, intptr_t);
887         base = 16;
888       } else {
889         write(STDERR_FILENO, "Unimplemented TracePrintf format\n", 33);
890         write(STDERR_FILENO, p, 2);
891         write(STDERR_FILENO, "\n", 1);
892         abort();
893       }
894       p++;
895       if (base != 0) {
896         bool minus = (l < 0 && base == 10);
897         uint64 ul = minus? -l : l;
898         do {
899           *--s = "0123456789abcdef"[ul % base];
900           ul /= base;
901         } while (ul != 0);
902         if (base == 16) {
903           *--s = 'x';
904           *--s = '0';
905         } else if (minus) {
906           *--s = '-';
907         }
908       }
909     } else {                        // handle normal characters
910       *--s = *p++;
911     }
912     while (*s != 0) {
913       if (i == sizeof(buf)) {
914         write(fd, buf, i);
915         i = 0;
916       }
917       buf[i++] = *s++;
918     }
919   }
920   if (i != 0) {
921     write(fd, buf, i);
922   }
923   va_end(ap);
924 }
925
926 // Return the file descriptor we're writing a log to
927 static int TraceFd() {
928   static int trace_fd = -1;
929   if (trace_fd == -1) {            // Open the trace file on the first call
930     trace_fd = open("/tmp/google.alloc", O_CREAT|O_TRUNC|O_WRONLY, 0666);
931     if (trace_fd == -1) {
932       trace_fd = 2;
933       TracePrintf(trace_fd,
934                   "Can't open /tmp/google.alloc.  Logging to stderr.\n");
935     }
936     // Add a header to the log.
937     TracePrintf(trace_fd, "Trace started: %lu\n",
938                 static_cast<unsigned long>(time(NULL)));
939     TracePrintf(trace_fd,
940                 "func\tsize\tptr\tthread_id\tstack pcs for tools/symbolize\n");
941   }
942   return trace_fd;
943 }
944
945 // Print the hex stack dump on a single line.   PCs are separated by tabs.
946 static void TraceStack(void) {
947   void *pcs[16];
948   int n = GetStackTrace(pcs, sizeof(pcs)/sizeof(pcs[0]), 0);
949   for (int i = 0; i != n; i++) {
950     TracePrintf(TraceFd(), "\t%p", pcs[i]);
951   }
952 }
953
954 // This protects MALLOC_TRACE, to make sure its info is atomically written.
955 static SpinLock malloc_trace_lock(SpinLock::LINKER_INITIALIZED);
956
957 #define MALLOC_TRACE(name, size, addr)                                  \
958   do {                                                                  \
959     if (FLAGS_malloctrace) {                                            \
960       SpinLockHolder l(&malloc_trace_lock);                             \
961       TracePrintf(TraceFd(), "%s\t%"PRIuS"\t%p\t%"GPRIuPTHREAD,         \
962                   name, size, addr, PRINTABLE_PTHREAD(pthread_self())); \
963       TraceStack();                                                     \
964       TracePrintf(TraceFd(), "\n");                                     \
965     }                                                                   \
966   } while (0)
967
968 // ========================================================================= //
969
970 // Write the characters buf[0, ..., size-1] to
971 // the malloc trace buffer.
972 // This function is intended for debugging,
973 // and is not declared in any header file.
974 // You must insert a declaration of it by hand when you need
975 // to use it.
976 void __malloctrace_write(const char *buf, size_t size) {
977   if (FLAGS_malloctrace) {
978     write(TraceFd(), buf, size);
979   }
980 }
981
982 // ========================================================================= //
983
984 // General debug allocation/deallocation
985
986 static inline void* DebugAllocate(size_t size, int type) {
987   MallocBlock* ptr = MallocBlock::Allocate(size, type);
988   if (ptr == NULL)  return NULL;
989   MALLOC_TRACE("malloc", size, ptr->data_addr());
990   return ptr->data_addr();
991 }
992
993 static inline void DebugDeallocate(void* ptr, int type) {
994   MALLOC_TRACE("free",
995                (ptr != 0 ? MallocBlock::FromRawPointer(ptr)->data_size() : 0),
996                ptr);
997   if (ptr)  MallocBlock::FromRawPointer(ptr)->Deallocate(type);
998 }
999
1000 // ========================================================================= //
1001
1002 // The following functions may be called via MallocExtension::instance()
1003 // for memory verification and statistics.
1004 class DebugMallocImplementation : public TCMallocImplementation {
1005  public:
1006   virtual bool GetNumericProperty(const char* name, size_t* value) {
1007     bool result = TCMallocImplementation::GetNumericProperty(name, value);
1008     if (result && (strcmp(name, "generic.current_allocated_bytes") == 0)) {
1009       // Subtract bytes kept in the free queue
1010       size_t qsize = MallocBlock::FreeQueueSize();
1011       if (*value >= qsize) {
1012         *value -= qsize;
1013       }
1014     }
1015     return result;
1016   }
1017
1018   virtual bool VerifyNewMemory(const void* p) {
1019     if (p)  MallocBlock::FromRawPointer(p)->Check(MallocBlock::kNewType);
1020     return true;
1021   }
1022
1023   virtual bool VerifyArrayNewMemory(const void* p) {
1024     if (p)  MallocBlock::FromRawPointer(p)->Check(MallocBlock::kArrayNewType);
1025     return true;
1026   }
1027
1028   virtual bool VerifyMallocMemory(const void* p) {
1029     if (p)  MallocBlock::FromRawPointer(p)->Check(MallocBlock::kMallocType);
1030     return true;
1031   }
1032
1033   virtual bool VerifyAllMemory() {
1034     return MallocBlock::CheckEverything();
1035   }
1036
1037   virtual bool MallocMemoryStats(int* blocks, size_t* total,
1038                                  int histogram[kMallocHistogramSize]) {
1039     return MallocBlock::MemoryStats(blocks, total, histogram);
1040   }
1041
1042   virtual size_t GetEstimatedAllocatedSize(size_t size) {
1043     return size;
1044   }
1045
1046   virtual size_t GetAllocatedSize(const void* p) {
1047     if (p) {
1048       RAW_CHECK(GetOwnership(p) != MallocExtension::kNotOwned,
1049                 "ptr not allocated by tcmalloc");
1050       return MallocBlock::FromRawPointer(p)->data_size();
1051     }
1052     return 0;
1053   }
1054
1055   virtual MallocExtension::Ownership GetOwnership(const void* p) {
1056     if (p) {
1057       const MallocBlock* mb = MallocBlock::FromRawPointer(p);
1058       return TCMallocImplementation::GetOwnership(mb);
1059     }
1060     return MallocExtension::kNotOwned;   // nobody owns NULL
1061   }
1062
1063   virtual void GetFreeListSizes(vector<MallocExtension::FreeListInfo>* v) {
1064     static const char* kDebugFreeQueue = "debug.free_queue";
1065
1066     TCMallocImplementation::GetFreeListSizes(v);
1067
1068     MallocExtension::FreeListInfo i;
1069     i.type = kDebugFreeQueue;
1070     i.min_object_size = 0;
1071     i.max_object_size = numeric_limits<size_t>::max();
1072     i.total_bytes_free = MallocBlock::FreeQueueSize();
1073     v->push_back(i);
1074   }
1075
1076  };
1077
1078 static DebugMallocImplementation debug_malloc_implementation;
1079
1080 REGISTER_MODULE_INITIALIZER(debugallocation, {
1081   // Either we or valgrind will control memory management.  We
1082   // register our extension if we're the winner. Otherwise let
1083   // Valgrind use its own malloc (so don't register our extension).
1084   if (!RunningOnValgrind()) {
1085     MallocExtension::Register(&debug_malloc_implementation);
1086   }
1087 });
1088
1089 REGISTER_MODULE_DESTRUCTOR(debugallocation, {
1090   if (!RunningOnValgrind()) {
1091     // When the program exits, check all blocks still in the free
1092     // queue for corruption.
1093     DanglingWriteChecker();
1094   }
1095 });
1096
1097 // ========================================================================= //
1098
1099 // This is mostly the same a cpp_alloc in tcmalloc.cc.
1100 // TODO(csilvers): change Allocate() above to call cpp_alloc, so we
1101 // don't have to reproduce the logic here.  To make tc_new_mode work
1102 // properly, I think we'll need to separate out the logic of throwing
1103 // from the logic of calling the new-handler.
1104 inline void* debug_cpp_alloc(size_t size, int new_type, bool nothrow) {
1105   for (;;) {
1106     void* p = DebugAllocate(size, new_type);
1107 #ifdef PREANSINEW
1108     return p;
1109 #else
1110     if (p == NULL) {  // allocation failed
1111       // Get the current new handler.  NB: this function is not
1112       // thread-safe.  We make a feeble stab at making it so here, but
1113       // this lock only protects against tcmalloc interfering with
1114       // itself, not with other libraries calling set_new_handler.
1115       std::new_handler nh;
1116       {
1117         SpinLockHolder h(&set_new_handler_lock);
1118         nh = std::set_new_handler(0);
1119         (void) std::set_new_handler(nh);
1120       }
1121 #if (defined(__GNUC__) && !defined(__EXCEPTIONS)) || (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS)
1122       if (nh) {
1123         // Since exceptions are disabled, we don't really know if new_handler
1124         // failed.  Assume it will abort if it fails.
1125         (*nh)();
1126         continue;
1127       }
1128       return 0;
1129 #else
1130       // If no new_handler is established, the allocation failed.
1131       if (!nh) {
1132         if (nothrow) return 0;
1133         throw std::bad_alloc();
1134       }
1135       // Otherwise, try the new_handler.  If it returns, retry the
1136       // allocation.  If it throws std::bad_alloc, fail the allocation.
1137       // if it throws something else, don't interfere.
1138       try {
1139         (*nh)();
1140       } catch (const std::bad_alloc&) {
1141         if (!nothrow) throw;
1142         return p;
1143       }
1144 #endif  // (defined(__GNUC__) && !defined(__EXCEPTIONS)) || (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS)
1145     } else {  // allocation success
1146       return p;
1147     }
1148 #endif  // PREANSINEW
1149   }
1150 }
1151
1152 inline void* do_debug_malloc_or_debug_cpp_alloc(size_t size) {
1153   return tc_new_mode ? debug_cpp_alloc(size, MallocBlock::kMallocType, true)
1154                      : DebugAllocate(size, MallocBlock::kMallocType);
1155 }
1156
1157 // Exported routines
1158
1159 extern "C" PERFTOOLS_DLL_DECL void* tc_malloc(size_t size) __THROW {
1160   void* ptr = do_debug_malloc_or_debug_cpp_alloc(size);
1161   MallocHook::InvokeNewHook(ptr, size);
1162   return ptr;
1163 }
1164
1165 extern "C" PERFTOOLS_DLL_DECL void tc_free(void* ptr) __THROW {
1166   MallocHook::InvokeDeleteHook(ptr);
1167   DebugDeallocate(ptr, MallocBlock::kMallocType);
1168 }
1169
1170 extern "C" PERFTOOLS_DLL_DECL void* tc_calloc(size_t count, size_t size) __THROW {
1171   // Overflow check
1172   const size_t total_size = count * size;
1173   if (size != 0 && total_size / size != count) return NULL;
1174
1175   void* block = do_debug_malloc_or_debug_cpp_alloc(total_size);
1176   MallocHook::InvokeNewHook(block, total_size);
1177   if (block)  memset(block, 0, total_size);
1178   return block;
1179 }
1180
1181 extern "C" PERFTOOLS_DLL_DECL void tc_cfree(void* ptr) __THROW {
1182   MallocHook::InvokeDeleteHook(ptr);
1183   DebugDeallocate(ptr, MallocBlock::kMallocType);
1184 }
1185
1186 extern "C" PERFTOOLS_DLL_DECL void* tc_realloc(void* ptr, size_t size) __THROW {
1187   if (ptr == NULL) {
1188     ptr = do_debug_malloc_or_debug_cpp_alloc(size);
1189     MallocHook::InvokeNewHook(ptr, size);
1190     return ptr;
1191   }
1192   if (size == 0) {
1193     MallocHook::InvokeDeleteHook(ptr);
1194     DebugDeallocate(ptr, MallocBlock::kMallocType);
1195     return NULL;
1196   }
1197   MallocBlock* old = MallocBlock::FromRawPointer(ptr);
1198   old->Check(MallocBlock::kMallocType);
1199   MallocBlock* p = MallocBlock::Allocate(size, MallocBlock::kMallocType);
1200
1201   // If realloc fails we are to leave the old block untouched and
1202   // return null
1203   if (p == NULL)  return NULL;
1204
1205   memcpy(p->data_addr(), old->data_addr(),
1206          (old->data_size() < size) ? old->data_size() : size);
1207   MallocHook::InvokeDeleteHook(ptr);
1208   MallocHook::InvokeNewHook(p->data_addr(), size);
1209   DebugDeallocate(ptr, MallocBlock::kMallocType);
1210   MALLOC_TRACE("realloc", p->data_size(), p->data_addr());
1211   return p->data_addr();
1212 }
1213
1214 extern "C" PERFTOOLS_DLL_DECL void* tc_new(size_t size) {
1215   void* ptr = debug_cpp_alloc(size, MallocBlock::kNewType, false);
1216   MallocHook::InvokeNewHook(ptr, size);
1217   if (ptr == NULL) {
1218     RAW_LOG(FATAL, "Unable to allocate %"PRIuS" bytes: new failed.", size);
1219   }
1220   return ptr;
1221 }
1222
1223 extern "C" PERFTOOLS_DLL_DECL void* tc_new_nothrow(size_t size, const std::nothrow_t&) __THROW {
1224   void* ptr = debug_cpp_alloc(size, MallocBlock::kNewType, true);
1225   MallocHook::InvokeNewHook(ptr, size);
1226   return ptr;
1227 }
1228
1229 extern "C" PERFTOOLS_DLL_DECL void tc_delete(void* p) __THROW {
1230   MallocHook::InvokeDeleteHook(p);
1231   DebugDeallocate(p, MallocBlock::kNewType);
1232 }
1233
1234 // Some STL implementations explicitly invoke this.
1235 // It is completely equivalent to a normal delete (delete never throws).
1236 extern "C" PERFTOOLS_DLL_DECL void tc_delete_nothrow(void* p, const std::nothrow_t&) __THROW {
1237   MallocHook::InvokeDeleteHook(p);
1238   DebugDeallocate(p, MallocBlock::kNewType);
1239 }
1240
1241 extern "C" PERFTOOLS_DLL_DECL void* tc_newarray(size_t size) {
1242   void* ptr = debug_cpp_alloc(size, MallocBlock::kArrayNewType, false);
1243   MallocHook::InvokeNewHook(ptr, size);
1244   if (ptr == NULL) {
1245     RAW_LOG(FATAL, "Unable to allocate %"PRIuS" bytes: new[] failed.", size);
1246   }
1247   return ptr;
1248 }
1249
1250 extern "C" PERFTOOLS_DLL_DECL void* tc_newarray_nothrow(size_t size, const std::nothrow_t&)
1251     __THROW {
1252   void* ptr = debug_cpp_alloc(size, MallocBlock::kArrayNewType, true);
1253   MallocHook::InvokeNewHook(ptr, size);
1254   return ptr;
1255 }
1256
1257 extern "C" PERFTOOLS_DLL_DECL void tc_deletearray(void* p) __THROW {
1258   MallocHook::InvokeDeleteHook(p);
1259   DebugDeallocate(p, MallocBlock::kArrayNewType);
1260 }
1261
1262 // Some STL implementations explicitly invoke this.
1263 // It is completely equivalent to a normal delete (delete never throws).
1264 extern "C" PERFTOOLS_DLL_DECL void tc_deletearray_nothrow(void* p, const std::nothrow_t&) __THROW {
1265   MallocHook::InvokeDeleteHook(p);
1266   DebugDeallocate(p, MallocBlock::kArrayNewType);
1267 }
1268
1269 // Round "value" up to next "alignment" boundary.
1270 // Requires that "alignment" be a power of two.
1271 static intptr_t RoundUp(intptr_t value, intptr_t alignment) {
1272   return (value + alignment - 1) & ~(alignment - 1);
1273 }
1274
1275 // This is mostly the same as do_memalign in tcmalloc.cc.
1276 static void *do_debug_memalign(size_t alignment, size_t size) {
1277   // Allocate >= size bytes aligned on "alignment" boundary
1278   // "alignment" is a power of two.
1279   void *p = 0;
1280   RAW_CHECK((alignment & (alignment-1)) == 0, "must be power of two");
1281   const size_t data_offset = MallocBlock::data_offset();
1282   // Allocate "alignment-1" extra bytes to ensure alignment is possible, and
1283   // a further data_offset bytes for an additional fake header.
1284   size_t extra_bytes = data_offset + alignment - 1;
1285   if (size + extra_bytes < size) return NULL;         // Overflow
1286   p = DebugAllocate(size + extra_bytes, MallocBlock::kMallocType);
1287   if (p != 0) {
1288     intptr_t orig_p = reinterpret_cast<intptr_t>(p);
1289     // Leave data_offset bytes for fake header, and round up to meet
1290     // alignment.
1291     p = reinterpret_cast<void *>(RoundUp(orig_p + data_offset, alignment));
1292     // Create a fake header block with an offset_ that points back to the
1293     // real header.  FromRawPointer uses this value.
1294     MallocBlock *fake_hdr = reinterpret_cast<MallocBlock *>(
1295                 reinterpret_cast<char *>(p) - data_offset);
1296     // offset_ is distance between real and fake headers.
1297     // p is now end of fake header (beginning of client area),
1298     // and orig_p is the end of the real header, so offset_
1299     // is their difference.
1300     fake_hdr->set_offset(reinterpret_cast<intptr_t>(p) - orig_p);
1301   }
1302   return p;
1303 }
1304
1305 // This is mostly the same as cpp_memalign in tcmalloc.cc.
1306 static void* debug_cpp_memalign(size_t align, size_t size) {
1307   for (;;) {
1308     void* p = do_debug_memalign(align, size);
1309 #ifdef PREANSINEW
1310     return p;
1311 #else
1312     if (p == NULL) {  // allocation failed
1313       // Get the current new handler.  NB: this function is not
1314       // thread-safe.  We make a feeble stab at making it so here, but
1315       // this lock only protects against tcmalloc interfering with
1316       // itself, not with other libraries calling set_new_handler.
1317       std::new_handler nh;
1318       {
1319         SpinLockHolder h(&set_new_handler_lock);
1320         nh = std::set_new_handler(0);
1321         (void) std::set_new_handler(nh);
1322       }
1323 #if (defined(__GNUC__) && !defined(__EXCEPTIONS)) || (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS)
1324       if (nh) {
1325         // Since exceptions are disabled, we don't really know if new_handler
1326         // failed.  Assume it will abort if it fails.
1327         (*nh)();
1328         continue;
1329       }
1330       return 0;
1331 #else
1332       // If no new_handler is established, the allocation failed.
1333       if (!nh)
1334         return 0;
1335
1336       // Otherwise, try the new_handler.  If it returns, retry the
1337       // allocation.  If it throws std::bad_alloc, fail the allocation.
1338       // if it throws something else, don't interfere.
1339       try {
1340         (*nh)();
1341       } catch (const std::bad_alloc&) {
1342         return p;
1343       }
1344 #endif  // (defined(__GNUC__) && !defined(__EXCEPTIONS)) || (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS)
1345     } else {  // allocation success
1346       return p;
1347     }
1348 #endif  // PREANSINEW
1349   }
1350 }
1351
1352 inline void* do_debug_memalign_or_debug_cpp_memalign(size_t align,
1353                                                      size_t size) {
1354   return tc_new_mode ? debug_cpp_memalign(align, size)
1355                      : do_debug_memalign(align, size);
1356 }
1357
1358 extern "C" PERFTOOLS_DLL_DECL void* tc_memalign(size_t align, size_t size) __THROW {
1359   void *p = do_debug_memalign_or_debug_cpp_memalign(align, size);
1360   MallocHook::InvokeNewHook(p, size);
1361   return p;
1362 }
1363
1364 // Implementation taken from tcmalloc/tcmalloc.cc
1365 extern "C" PERFTOOLS_DLL_DECL int tc_posix_memalign(void** result_ptr, size_t align, size_t size)
1366     __THROW {
1367   if (((align % sizeof(void*)) != 0) ||
1368       ((align & (align - 1)) != 0) ||
1369       (align == 0)) {
1370     return EINVAL;
1371   }
1372
1373   void* result = do_debug_memalign_or_debug_cpp_memalign(align, size);
1374   MallocHook::InvokeNewHook(result, size);
1375   if (result == NULL) {
1376     return ENOMEM;
1377   } else {
1378     *result_ptr = result;
1379     return 0;
1380   }
1381 }
1382
1383 extern "C" PERFTOOLS_DLL_DECL void* tc_valloc(size_t size) __THROW {
1384   // Allocate >= size bytes starting on a page boundary
1385   void *p = do_debug_memalign_or_debug_cpp_memalign(getpagesize(), size);
1386   MallocHook::InvokeNewHook(p, size);
1387   return p;
1388 }
1389
1390 extern "C" PERFTOOLS_DLL_DECL void* tc_pvalloc(size_t size) __THROW {
1391   // Round size up to a multiple of pages
1392   // then allocate memory on a page boundary
1393   int pagesize = getpagesize();
1394   size = RoundUp(size, pagesize);
1395   if (size == 0) {     // pvalloc(0) should allocate one page, according to
1396     size = pagesize;   // http://man.free4web.biz/man3/libmpatrol.3.html
1397   }
1398   void *p = do_debug_memalign_or_debug_cpp_memalign(pagesize, size);
1399   MallocHook::InvokeNewHook(p, size);
1400   return p;
1401 }
1402
1403 // malloc_stats just falls through to the base implementation.
1404 extern "C" PERFTOOLS_DLL_DECL void tc_malloc_stats(void) __THROW {
1405   BASE_MALLOC_STATS();
1406 }
1407
1408 extern "C" PERFTOOLS_DLL_DECL int tc_mallopt(int cmd, int value) __THROW {
1409   return BASE_MALLOPT(cmd, value);
1410 }
1411
1412 #ifdef HAVE_STRUCT_MALLINFO
1413 extern "C" PERFTOOLS_DLL_DECL struct mallinfo tc_mallinfo(void) __THROW {
1414   return BASE_MALLINFO();
1415 }
1416 #endif
1417
1418 extern "C" PERFTOOLS_DLL_DECL size_t tc_malloc_size(void* ptr) __THROW {
1419   return MallocExtension::instance()->GetAllocatedSize(ptr);
1420 }