blob: bb99b690085fe89d6e1bad3011a4c61d14a77f7c [file] [log] [blame]
Austin Schuh745610d2015-09-06 18:19:50 -07001// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
2// Copyright (c) 2011, Google Inc.
3// All rights reserved.
4//
5// Redistribution and use in source and binary forms, with or without
6// modification, are permitted provided that the following conditions are
7// met:
8//
9// * Redistributions of source code must retain the above copyright
10// notice, this list of conditions and the following disclaimer.
11// * Redistributions in binary form must reproduce the above
12// copyright notice, this list of conditions and the following disclaimer
13// in the documentation and/or other materials provided with the
14// distribution.
15// * Neither the name of Google Inc. nor the names of its
16// contributors may be used to endorse or promote products derived from
17// this software without specific prior written permission.
18//
19// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31// ---
32// Author: Craig Silverstein <opensource@google.com>
33//
34// Used to override malloc routines on systems that define the
35// memory allocation routines to be weak symbols in their libc
36// (almost all unix-based systems are like this), on gcc, which
37// suppports the 'alias' attribute.
38
39#ifndef TCMALLOC_LIBC_OVERRIDE_GCC_AND_WEAK_INL_H_
40#define TCMALLOC_LIBC_OVERRIDE_GCC_AND_WEAK_INL_H_
41
42#ifdef HAVE_SYS_CDEFS_H
43#include <sys/cdefs.h> // for __THROW
44#endif
45#include <gperftools/tcmalloc.h>
46
Brian Silverman20350ac2021-11-17 18:19:55 -080047#include "getenv_safe.h" // TCMallocGetenvSafe
48#include "base/commandlineflags.h"
49
Austin Schuh745610d2015-09-06 18:19:50 -070050#ifndef __THROW // I guess we're not on a glibc-like system
51# define __THROW // __THROW is just an optimization, so ok to make it ""
52#endif
53
54#ifndef __GNUC__
55# error libc_override_gcc_and_weak.h is for gcc distributions only.
56#endif
57
Brian Silverman20350ac2021-11-17 18:19:55 -080058#define ALIAS(tc_fn) __attribute__ ((alias (#tc_fn), used))
Austin Schuh745610d2015-09-06 18:19:50 -070059
Brian Silverman20350ac2021-11-17 18:19:55 -080060void* operator new(size_t size) CPP_BADALLOC ALIAS(tc_new);
61void operator delete(void* p) CPP_NOTHROW ALIAS(tc_delete);
62void* operator new[](size_t size) CPP_BADALLOC ALIAS(tc_newarray);
63void operator delete[](void* p) CPP_NOTHROW ALIAS(tc_deletearray);
64void* operator new(size_t size, const std::nothrow_t& nt) CPP_NOTHROW
65 ALIAS(tc_new_nothrow);
66void* operator new[](size_t size, const std::nothrow_t& nt) CPP_NOTHROW
67 ALIAS(tc_newarray_nothrow);
68void operator delete(void* p, const std::nothrow_t& nt) CPP_NOTHROW
69 ALIAS(tc_delete_nothrow);
70void operator delete[](void* p, const std::nothrow_t& nt) CPP_NOTHROW
71 ALIAS(tc_deletearray_nothrow);
72
73#if defined(ENABLE_SIZED_DELETE)
74
75void operator delete(void *p, size_t size) CPP_NOTHROW
76 ALIAS(tc_delete_sized);
77void operator delete[](void *p, size_t size) CPP_NOTHROW
78 ALIAS(tc_deletearray_sized);
79
80#elif defined(ENABLE_DYNAMIC_SIZED_DELETE) && \
81 (__GNUC__ * 100 + __GNUC_MINOR__) >= 405
82
83static void delegate_sized_delete(void *p, size_t s) {
84 (operator delete)(p);
85}
86
87static void delegate_sized_deletearray(void *p, size_t s) {
88 (operator delete[])(p);
89}
90
91extern "C" __attribute__((weak))
92int tcmalloc_sized_delete_enabled(void);
93
94static bool sized_delete_enabled(void) {
95 if (tcmalloc_sized_delete_enabled != 0) {
96 return !!tcmalloc_sized_delete_enabled();
97 }
98
99 const char *flag = TCMallocGetenvSafe("TCMALLOC_ENABLE_SIZED_DELETE");
100 return tcmalloc::commandlineflags::StringToBool(flag, false);
101}
102
103extern "C" {
104
105static void *resolve_delete_sized(void) {
106 if (sized_delete_enabled()) {
107 return reinterpret_cast<void *>(tc_delete_sized);
108 }
109 return reinterpret_cast<void *>(delegate_sized_delete);
110}
111
112static void *resolve_deletearray_sized(void) {
113 if (sized_delete_enabled()) {
114 return reinterpret_cast<void *>(tc_deletearray_sized);
115 }
116 return reinterpret_cast<void *>(delegate_sized_deletearray);
117}
118
119}
120
121void operator delete(void *p, size_t size) CPP_NOTHROW
122 __attribute__((ifunc("resolve_delete_sized")));
123void operator delete[](void *p, size_t size) CPP_NOTHROW
124 __attribute__((ifunc("resolve_deletearray_sized")));
125
126#else /* !ENABLE_SIZED_DELETE && !ENABLE_DYN_SIZED_DELETE */
127
128void operator delete(void *p, size_t size) CPP_NOTHROW
129 ALIAS(tc_delete_sized);
130void operator delete[](void *p, size_t size) CPP_NOTHROW
131 ALIAS(tc_deletearray_sized);
132
133#endif /* !ENABLE_SIZED_DELETE && !ENABLE_DYN_SIZED_DELETE */
134
135#if defined(ENABLE_ALIGNED_NEW_DELETE)
136
137void* operator new(size_t size, std::align_val_t al)
138 ALIAS(tc_new_aligned);
139void operator delete(void* p, std::align_val_t al) CPP_NOTHROW
140 ALIAS(tc_delete_aligned);
141void* operator new[](size_t size, std::align_val_t al)
142 ALIAS(tc_newarray_aligned);
143void operator delete[](void* p, std::align_val_t al) CPP_NOTHROW
144 ALIAS(tc_deletearray_aligned);
145void* operator new(size_t size, std::align_val_t al, const std::nothrow_t& nt) CPP_NOTHROW
146 ALIAS(tc_new_aligned_nothrow);
147void* operator new[](size_t size, std::align_val_t al, const std::nothrow_t& nt) CPP_NOTHROW
148 ALIAS(tc_newarray_aligned_nothrow);
149void operator delete(void* p, std::align_val_t al, const std::nothrow_t& nt) CPP_NOTHROW
150 ALIAS(tc_delete_aligned_nothrow);
151void operator delete[](void* p, std::align_val_t al, const std::nothrow_t& nt) CPP_NOTHROW
152 ALIAS(tc_deletearray_aligned_nothrow);
153
154#if defined(ENABLE_SIZED_DELETE)
155
156void operator delete(void *p, size_t size, std::align_val_t al) CPP_NOTHROW
157 ALIAS(tc_delete_sized_aligned);
158void operator delete[](void *p, size_t size, std::align_val_t al) CPP_NOTHROW
159 ALIAS(tc_deletearray_sized_aligned);
160
161#else /* defined(ENABLE_SIZED_DELETE) */
162
163#if defined(ENABLE_DYNAMIC_SIZED_DELETE) && \
164 (__GNUC__ * 100 + __GNUC_MINOR__) >= 405
165
166static void delegate_sized_aligned_delete(void *p, size_t s, std::align_val_t al) {
167 (operator delete)(p, al);
168}
169
170static void delegate_sized_aligned_deletearray(void *p, size_t s, std::align_val_t al) {
171 (operator delete[])(p, al);
172}
173
174extern "C" {
175
176static void *resolve_delete_sized_aligned(void) {
177 if (sized_delete_enabled()) {
178 return reinterpret_cast<void *>(tc_delete_sized_aligned);
179 }
180 return reinterpret_cast<void *>(delegate_sized_aligned_delete);
181}
182
183static void *resolve_deletearray_sized_aligned(void) {
184 if (sized_delete_enabled()) {
185 return reinterpret_cast<void *>(tc_deletearray_sized_aligned);
186 }
187 return reinterpret_cast<void *>(delegate_sized_aligned_deletearray);
188}
189
190}
191
192void operator delete(void *p, size_t size, std::align_val_t al) CPP_NOTHROW
193 __attribute__((ifunc("resolve_delete_sized_aligned")));
194void operator delete[](void *p, size_t size, std::align_val_t al) CPP_NOTHROW
195 __attribute__((ifunc("resolve_deletearray_sized_aligned")));
196
197#else /* defined(ENABLE_DYN_SIZED_DELETE) */
198
199void operator delete(void *p, size_t size, std::align_val_t al) CPP_NOTHROW
200 ALIAS(tc_delete_sized_aligned);
201void operator delete[](void *p, size_t size, std::align_val_t al) CPP_NOTHROW
202 ALIAS(tc_deletearray_sized_aligned);
203
204#endif /* defined(ENABLE_DYN_SIZED_DELETE) */
205
206#endif /* defined(ENABLE_SIZED_DELETE) */
207
208#endif /* defined(ENABLE_ALIGNED_NEW_DELETE) */
Austin Schuh745610d2015-09-06 18:19:50 -0700209
210extern "C" {
211 void* malloc(size_t size) __THROW ALIAS(tc_malloc);
212 void free(void* ptr) __THROW ALIAS(tc_free);
213 void* realloc(void* ptr, size_t size) __THROW ALIAS(tc_realloc);
214 void* calloc(size_t n, size_t size) __THROW ALIAS(tc_calloc);
215 void cfree(void* ptr) __THROW ALIAS(tc_cfree);
216 void* memalign(size_t align, size_t s) __THROW ALIAS(tc_memalign);
Brian Silverman20350ac2021-11-17 18:19:55 -0800217 void* aligned_alloc(size_t align, size_t s) __THROW ALIAS(tc_memalign);
Austin Schuh745610d2015-09-06 18:19:50 -0700218 void* valloc(size_t size) __THROW ALIAS(tc_valloc);
219 void* pvalloc(size_t size) __THROW ALIAS(tc_pvalloc);
220 int posix_memalign(void** r, size_t a, size_t s) __THROW
221 ALIAS(tc_posix_memalign);
222#ifndef __UCLIBC__
223 void malloc_stats(void) __THROW ALIAS(tc_malloc_stats);
224#endif
225 int mallopt(int cmd, int value) __THROW ALIAS(tc_mallopt);
226#ifdef HAVE_STRUCT_MALLINFO
227 struct mallinfo mallinfo(void) __THROW ALIAS(tc_mallinfo);
228#endif
229 size_t malloc_size(void* p) __THROW ALIAS(tc_malloc_size);
230#if defined(__ANDROID__)
231 size_t malloc_usable_size(const void* p) __THROW
232 ALIAS(tc_malloc_size);
233#else
234 size_t malloc_usable_size(void* p) __THROW ALIAS(tc_malloc_size);
235#endif
236} // extern "C"
237
238#undef ALIAS
239
240// No need to do anything at tcmalloc-registration time: we do it all
241// via overriding weak symbols (at link time).
242static void ReplaceSystemAlloc() { }
243
244#endif // TCMALLOC_LIBC_OVERRIDE_GCC_AND_WEAK_INL_H_