blob: 662520c150b4f436f1476001235d30ff0a2ef178 [file] [log] [blame]
Christopher Ferrisdb478a62018-02-07 18:42:14 -08001/*
2 * Copyright (C) 2018 The Android Open Source Project
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
7 * are met:
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 copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
13 * distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#include <errno.h>
30#include <malloc.h>
31#include <stdint.h>
32#include <string.h>
33#include <sys/param.h>
34#include <unistd.h>
35
36#include <private/bionic_malloc_dispatch.h>
37
38// ------------------------------------------------------------------------
39// Global Data
40// ------------------------------------------------------------------------
41const MallocDispatch* g_dispatch;
42// ------------------------------------------------------------------------
43
44// ------------------------------------------------------------------------
45// Use C style prototypes for all exported functions. This makes it easy
46// to do dlsym lookups during libc initialization when hooks are enabled.
47// ------------------------------------------------------------------------
48__BEGIN_DECLS
49
50bool hooks_initialize(const MallocDispatch* malloc_dispatch, int* malloc_zygote_child,
51 const char* options);
52void hooks_finalize();
53void hooks_get_malloc_leak_info(
54 uint8_t** info, size_t* overall_size, size_t* info_size, size_t* total_memory,
55 size_t* backtrace_size);
56ssize_t hooks_malloc_backtrace(void* pointer, uintptr_t* frames, size_t frame_count);
57void hooks_free_malloc_leak_info(uint8_t* info);
58size_t hooks_malloc_usable_size(void* pointer);
59void* hooks_malloc(size_t size);
60void hooks_free(void* pointer);
61void* hooks_memalign(size_t alignment, size_t bytes);
62void* hooks_aligned_alloc(size_t alignment, size_t bytes);
63void* hooks_realloc(void* pointer, size_t bytes);
64void* hooks_calloc(size_t nmemb, size_t bytes);
65struct mallinfo hooks_mallinfo();
66int hooks_mallopt(int param, int value);
67int hooks_posix_memalign(void** memptr, size_t alignment, size_t size);
68int hooks_iterate(uintptr_t base, size_t size,
69 void (*callback)(uintptr_t base, size_t size, void* arg), void* arg);
70void hooks_malloc_disable();
71void hooks_malloc_enable();
72
73#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
74void* hooks_pvalloc(size_t bytes);
75void* hooks_valloc(size_t size);
76#endif
77
78static void* default_malloc_hook(size_t bytes, const void*) {
79 return g_dispatch->malloc(bytes);
80}
81
82static void* default_realloc_hook(void* pointer, size_t bytes, const void*) {
83 return g_dispatch->realloc(pointer, bytes);
84}
85
86static void default_free_hook(void* pointer, const void*) {
87 g_dispatch->free(pointer);
88}
89
90static void* default_memalign_hook(size_t alignment, size_t bytes, const void*) {
91 return g_dispatch->memalign(alignment, bytes);
92}
93
94__END_DECLS
95// ------------------------------------------------------------------------
96
97bool hooks_initialize(const MallocDispatch* malloc_dispatch, int*, const char*) {
98 g_dispatch = malloc_dispatch;
99 __malloc_hook = default_malloc_hook;
100 __realloc_hook = default_realloc_hook;
101 __free_hook = default_free_hook;
102 __memalign_hook = default_memalign_hook;
103 return true;
104}
105
106void hooks_finalize() {
107}
108
109void hooks_get_malloc_leak_info(uint8_t** info, size_t* overall_size,
110 size_t* info_size, size_t* total_memory, size_t* backtrace_size) {
111 *info = nullptr;
112 *overall_size = 0;
113 *info_size = 0;
114 *total_memory = 0;
115 *backtrace_size = 0;
116}
117
118void hooks_free_malloc_leak_info(uint8_t*) {
119}
120
121size_t hooks_malloc_usable_size(void* pointer) {
122 return g_dispatch->malloc_usable_size(pointer);
123}
124
125void* hooks_malloc(size_t size) {
126 if (__malloc_hook != nullptr && __malloc_hook != default_malloc_hook) {
127 return __malloc_hook(size, __builtin_return_address(0));
128 }
129 return g_dispatch->malloc(size);
130}
131
132void hooks_free(void* pointer) {
133 if (__free_hook != nullptr && __free_hook != default_free_hook) {
134 return __free_hook(pointer, __builtin_return_address(0));
135 }
136 return g_dispatch->free(pointer);
137}
138
139void* hooks_memalign(size_t alignment, size_t bytes) {
140 if (__memalign_hook != nullptr && __memalign_hook != default_memalign_hook) {
141 return __memalign_hook(alignment, bytes, __builtin_return_address(0));
142 }
143 return g_dispatch->memalign(alignment, bytes);
144}
145
146void* hooks_realloc(void* pointer, size_t bytes) {
147 if (__realloc_hook != nullptr && __realloc_hook != default_realloc_hook) {
148 return __realloc_hook(pointer, bytes, __builtin_return_address(0));
149 }
150 return g_dispatch->realloc(pointer, bytes);
151}
152
153void* hooks_calloc(size_t nmemb, size_t bytes) {
154 if (__malloc_hook != nullptr && __malloc_hook != default_malloc_hook) {
155 size_t size;
156 if (__builtin_mul_overflow(nmemb, bytes, &size)) {
157 return nullptr;
158 }
159 void* ptr = __malloc_hook(size, __builtin_return_address(0));
160 if (ptr != nullptr) {
161 memset(ptr, 0, size);
162 }
163 return ptr;
164 }
165 return g_dispatch->calloc(nmemb, bytes);
166}
167
168struct mallinfo hooks_mallinfo() {
169 return g_dispatch->mallinfo();
170}
171
172int hooks_mallopt(int param, int value) {
173 return g_dispatch->mallopt(param, value);
174}
175
176void* hooks_aligned_alloc(size_t alignment, size_t size) {
177 if (__memalign_hook != nullptr && __memalign_hook != default_memalign_hook) {
178 if (!powerof2(alignment)) {
179 errno = EINVAL;
180 return nullptr;
181 }
182 void* ptr = __memalign_hook(alignment, size, __builtin_return_address(0));
183 if (ptr == nullptr) {
184 errno = ENOMEM;
185 }
186 return ptr;
187 }
188 return g_dispatch->aligned_alloc(alignment, size);
189}
190
191int hooks_posix_memalign(void** memptr, size_t alignment, size_t size) {
192 if (__memalign_hook != nullptr && __memalign_hook != default_memalign_hook) {
193 if (!powerof2(alignment)) {
194 return EINVAL;
195 }
196 *memptr = __memalign_hook(alignment, size, __builtin_return_address(0));
197 if (*memptr == nullptr) {
198 return ENOMEM;
199 }
200 return 0;
201 }
202 return g_dispatch->posix_memalign(memptr, alignment, size);
203}
204
205int hooks_iterate(uintptr_t, size_t, void (*)(uintptr_t, size_t, void*), void*) {
206 return 0;
207}
208
209void hooks_malloc_disable() {
210}
211
212void hooks_malloc_enable() {
213}
214
215ssize_t hooks_malloc_backtrace(void*, uintptr_t*, size_t) {
216 return 0;
217}
218
219#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
220void* hooks_pvalloc(size_t bytes) {
221 size_t pagesize = getpagesize();
222 size_t size = __BIONIC_ALIGN(bytes, pagesize);
223 if (size < bytes) {
224 // Overflow
225 errno = ENOMEM;
226 return nullptr;
227 }
228 return hooks_memalign(pagesize, size);
229}
230
231void* hooks_valloc(size_t size) {
232 return hooks_memalign(getpagesize(), size);
233}
234#endif