blob: 093bdee8cc501b1ae68a2074f750fb9e486ec82c [file] [log] [blame]
Christopher Ferris63860cb2015-11-16 17:30:32 -08001/*
2 * Copyright (C) 2012 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 <inttypes.h>
31#include <malloc.h>
Christopher Ferris6c619a02019-03-01 17:59:51 -080032#include <stdio.h>
Christopher Ferris63860cb2015-11-16 17:30:32 -080033#include <string.h>
34#include <sys/cdefs.h>
35#include <sys/param.h>
36#include <unistd.h>
37
Christopher Ferris602b88c2017-08-04 13:04:04 -070038#include <mutex>
Christopher Ferris63860cb2015-11-16 17:30:32 -080039#include <vector>
40
Christopher Ferris602b88c2017-08-04 13:04:04 -070041#include <android-base/file.h>
Christopher Ferris2e1a40a2018-06-13 10:46:34 -070042#include <android-base/properties.h>
Christopher Ferris602b88c2017-08-04 13:04:04 -070043#include <android-base/stringprintf.h>
Christopher Ferris63860cb2015-11-16 17:30:32 -080044#include <private/bionic_malloc_dispatch.h>
Christopher Ferris6c619a02019-03-01 17:59:51 -080045#include <private/MallocXmlElem.h>
Christopher Ferris63860cb2015-11-16 17:30:32 -080046
Christopher Ferris72df6702016-02-11 15:51:31 -080047#include "Config.h"
Christopher Ferris63860cb2015-11-16 17:30:32 -080048#include "DebugData.h"
Christopher Ferris4da25032018-03-07 13:38:48 -080049#include "backtrace.h"
Christopher Ferris63860cb2015-11-16 17:30:32 -080050#include "debug_disable.h"
51#include "debug_log.h"
52#include "malloc_debug.h"
Christopher Ferris93bdd6a2018-04-05 11:12:38 -070053#include "UnwindBacktrace.h"
Christopher Ferris63860cb2015-11-16 17:30:32 -080054
55// ------------------------------------------------------------------------
56// Global Data
57// ------------------------------------------------------------------------
58DebugData* g_debug;
59
60int* g_malloc_zygote_child;
61
62const MallocDispatch* g_dispatch;
63// ------------------------------------------------------------------------
64
65// ------------------------------------------------------------------------
66// Use C style prototypes for all exported functions. This makes it easy
67// to do dlsym lookups during libc initialization when malloc debug
68// is enabled.
69// ------------------------------------------------------------------------
70__BEGIN_DECLS
71
Tamas Berghammerac81fe82016-08-26 15:54:59 +010072bool debug_initialize(const MallocDispatch* malloc_dispatch, int* malloc_zygote_child,
Christopher Ferris4da25032018-03-07 13:38:48 -080073 const char* options);
Christopher Ferris63860cb2015-11-16 17:30:32 -080074void debug_finalize();
Christopher Ferris2e1a40a2018-06-13 10:46:34 -070075void debug_dump_heap(const char* file_name);
Christopher Ferris4da25032018-03-07 13:38:48 -080076void debug_get_malloc_leak_info(uint8_t** info, size_t* overall_size, size_t* info_size,
77 size_t* total_memory, size_t* backtrace_size);
Christopher Ferris2e1a40a2018-06-13 10:46:34 -070078bool debug_write_malloc_leak_info(FILE* fp);
Colin Cross2d4721c2016-02-02 11:57:54 -080079ssize_t debug_malloc_backtrace(void* pointer, uintptr_t* frames, size_t frame_count);
Christopher Ferris63860cb2015-11-16 17:30:32 -080080void debug_free_malloc_leak_info(uint8_t* info);
81size_t debug_malloc_usable_size(void* pointer);
82void* debug_malloc(size_t size);
83void debug_free(void* pointer);
Christopher Ferriscae21a92018-02-05 18:14:55 -080084void* debug_aligned_alloc(size_t alignment, size_t size);
Christopher Ferris63860cb2015-11-16 17:30:32 -080085void* debug_memalign(size_t alignment, size_t bytes);
86void* debug_realloc(void* pointer, size_t bytes);
87void* debug_calloc(size_t nmemb, size_t bytes);
88struct mallinfo debug_mallinfo();
Christopher Ferrisa1c0d2f2017-05-15 15:50:19 -070089int debug_mallopt(int param, int value);
Christopher Ferris6c619a02019-03-01 17:59:51 -080090int debug_malloc_info(int options, FILE* fp);
Christopher Ferris63860cb2015-11-16 17:30:32 -080091int debug_posix_memalign(void** memptr, size_t alignment, size_t size);
Colin Cross869691c2016-01-29 12:48:18 -080092int debug_iterate(uintptr_t base, size_t size,
Christopher Ferris4da25032018-03-07 13:38:48 -080093 void (*callback)(uintptr_t base, size_t size, void* arg), void* arg);
Colin Cross869691c2016-01-29 12:48:18 -080094void debug_malloc_disable();
95void debug_malloc_enable();
Christopher Ferris63860cb2015-11-16 17:30:32 -080096
97#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
98void* debug_pvalloc(size_t bytes);
99void* debug_valloc(size_t size);
100#endif
101
102__END_DECLS
103// ------------------------------------------------------------------------
104
Colin Cross7a28a3c2016-02-07 22:51:15 -0800105static void InitAtfork() {
106 static pthread_once_t atfork_init = PTHREAD_ONCE_INIT;
Christopher Ferris4da25032018-03-07 13:38:48 -0800107 pthread_once(&atfork_init, []() {
Colin Cross7a28a3c2016-02-07 22:51:15 -0800108 pthread_atfork(
Christopher Ferris4da25032018-03-07 13:38:48 -0800109 []() {
Colin Cross7a28a3c2016-02-07 22:51:15 -0800110 if (g_debug != nullptr) {
111 g_debug->PrepareFork();
112 }
113 },
Christopher Ferris4da25032018-03-07 13:38:48 -0800114 []() {
Colin Cross7a28a3c2016-02-07 22:51:15 -0800115 if (g_debug != nullptr) {
116 g_debug->PostForkParent();
117 }
118 },
Christopher Ferris4da25032018-03-07 13:38:48 -0800119 []() {
Colin Cross7a28a3c2016-02-07 22:51:15 -0800120 if (g_debug != nullptr) {
121 g_debug->PostForkChild();
122 }
Christopher Ferris4da25032018-03-07 13:38:48 -0800123 });
Colin Cross7a28a3c2016-02-07 22:51:15 -0800124 });
125}
Christopher Ferrisd0919622016-03-15 22:39:39 -0700126
Christopher Ferris93bdd6a2018-04-05 11:12:38 -0700127void BacktraceAndLog() {
128 if (g_debug->config().options() & BACKTRACE_FULL) {
129 std::vector<uintptr_t> frames;
130 std::vector<unwindstack::LocalFrameData> frames_info;
131 if (!Unwind(&frames, &frames_info, 256)) {
132 error_log(" Backtrace failed to get any frames.");
133 } else {
134 UnwindLog(frames_info);
135 }
136 } else {
137 std::vector<uintptr_t> frames(256);
138 size_t num_frames = backtrace_get(frames.data(), frames.size());
139 if (num_frames == 0) {
140 error_log(" Backtrace failed to get any frames.");
141 } else {
142 backtrace_log(frames.data(), num_frames);
143 }
144 }
145}
146
Christopher Ferris4da25032018-03-07 13:38:48 -0800147static void LogError(const void* pointer, const char* error_str) {
Christopher Ferris63860cb2015-11-16 17:30:32 -0800148 error_log(LOG_DIVIDER);
Christopher Ferris4da25032018-03-07 13:38:48 -0800149 error_log("+++ ALLOCATION %p %s", pointer, error_str);
150
151 // If we are tracking already freed pointers, check to see if this is
152 // one so we can print extra information.
153 if (g_debug->config().options() & FREE_TRACK) {
154 PointerData::LogFreeBacktrace(pointer);
Christopher Ferris7993b802016-01-28 18:35:05 -0800155 }
Christopher Ferris4da25032018-03-07 13:38:48 -0800156
Christopher Ferris93bdd6a2018-04-05 11:12:38 -0700157 error_log("Backtrace at time of failure:");
158 BacktraceAndLog();
Christopher Ferris63860cb2015-11-16 17:30:32 -0800159 error_log(LOG_DIVIDER);
Iris Chang7f209a92019-01-16 11:17:15 +0800160 if (g_debug->config().options() & ABORT_ON_ERROR) {
161 abort();
162 }
Christopher Ferris63860cb2015-11-16 17:30:32 -0800163}
164
Christopher Ferris4da25032018-03-07 13:38:48 -0800165static bool VerifyPointer(const void* pointer, const char* function_name) {
166 if (g_debug->HeaderEnabled()) {
167 Header* header = g_debug->GetHeader(pointer);
168 if (header->tag != DEBUG_TAG) {
169 std::string error_str;
170 if (header->tag == DEBUG_FREE_TAG) {
171 error_str = std::string("USED AFTER FREE (") + function_name + ")";
172 } else {
173 error_str = android::base::StringPrintf("HAS INVALID TAG %" PRIx32 " (%s)", header->tag,
174 function_name);
175 }
176 LogError(pointer, error_str.c_str());
177 return false;
178 }
179 }
180
181 if (g_debug->TrackPointers()) {
182 if (!PointerData::Exists(pointer)) {
183 std::string error_str(std::string("UNKNOWN POINTER (") + function_name + ")");
184 LogError(pointer, error_str.c_str());
185 return false;
186 }
187 }
188 return true;
189}
190
191static size_t InternalMallocUsableSize(void* pointer) {
192 if (g_debug->HeaderEnabled()) {
193 return g_debug->GetHeader(pointer)->usable_size;
194 } else {
195 return g_dispatch->malloc_usable_size(pointer);
196 }
197}
198
Christopher Ferris63860cb2015-11-16 17:30:32 -0800199static void* InitHeader(Header* header, void* orig_pointer, size_t size) {
200 header->tag = DEBUG_TAG;
201 header->orig_pointer = orig_pointer;
202 header->size = size;
Christopher Ferris63860cb2015-11-16 17:30:32 -0800203 header->usable_size = g_dispatch->malloc_usable_size(orig_pointer);
204 if (header->usable_size == 0) {
205 g_dispatch->free(orig_pointer);
206 return nullptr;
207 }
Christopher Ferris4da25032018-03-07 13:38:48 -0800208 header->usable_size -= g_debug->pointer_offset() + reinterpret_cast<uintptr_t>(header) -
209 reinterpret_cast<uintptr_t>(orig_pointer);
Christopher Ferris63860cb2015-11-16 17:30:32 -0800210
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700211 if (g_debug->config().options() & FRONT_GUARD) {
Christopher Ferris63860cb2015-11-16 17:30:32 -0800212 uint8_t* guard = g_debug->GetFrontGuard(header);
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700213 memset(guard, g_debug->config().front_guard_value(), g_debug->config().front_guard_bytes());
Christopher Ferris63860cb2015-11-16 17:30:32 -0800214 }
215
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700216 if (g_debug->config().options() & REAR_GUARD) {
Christopher Ferris63860cb2015-11-16 17:30:32 -0800217 uint8_t* guard = g_debug->GetRearGuard(header);
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700218 memset(guard, g_debug->config().rear_guard_value(), g_debug->config().rear_guard_bytes());
Christopher Ferris63860cb2015-11-16 17:30:32 -0800219 // If the rear guard is enabled, set the usable size to the exact size
220 // of the allocation.
Christopher Ferris4da25032018-03-07 13:38:48 -0800221 header->usable_size = header->size;
Christopher Ferris63860cb2015-11-16 17:30:32 -0800222 }
223
224 return g_debug->GetPointer(header);
225}
226
Tamas Berghammerac81fe82016-08-26 15:54:59 +0100227bool debug_initialize(const MallocDispatch* malloc_dispatch, int* malloc_zygote_child,
Christopher Ferris4da25032018-03-07 13:38:48 -0800228 const char* options) {
Tamas Berghammerac81fe82016-08-26 15:54:59 +0100229 if (malloc_zygote_child == nullptr || options == nullptr) {
Christopher Ferris63860cb2015-11-16 17:30:32 -0800230 return false;
231 }
Colin Cross7a28a3c2016-02-07 22:51:15 -0800232
233 InitAtfork();
234
Christopher Ferris63860cb2015-11-16 17:30:32 -0800235 g_malloc_zygote_child = malloc_zygote_child;
236
237 g_dispatch = malloc_dispatch;
238
239 if (!DebugDisableInitialize()) {
240 return false;
241 }
242
243 DebugData* debug = new DebugData();
Tamas Berghammerac81fe82016-08-26 15:54:59 +0100244 if (!debug->Initialize(options)) {
Christopher Ferris63860cb2015-11-16 17:30:32 -0800245 delete debug;
246 DebugDisableFinalize();
247 return false;
248 }
249 g_debug = debug;
250
251 // Always enable the backtrace code since we will use it in a number
252 // of different error cases.
253 backtrace_startup();
254
255 return true;
256}
257
258void debug_finalize() {
259 if (g_debug == nullptr) {
260 return;
261 }
262
Christopher Ferris97b47472018-07-10 14:45:24 -0700263 // Turn off capturing allocations calls.
264 DebugDisableSet(true);
265
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700266 if (g_debug->config().options() & FREE_TRACK) {
Christopher Ferris4da25032018-03-07 13:38:48 -0800267 PointerData::VerifyAllFreed();
Christopher Ferris63860cb2015-11-16 17:30:32 -0800268 }
269
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700270 if (g_debug->config().options() & LEAK_TRACK) {
Christopher Ferris4da25032018-03-07 13:38:48 -0800271 PointerData::LogLeaks();
Christopher Ferris63860cb2015-11-16 17:30:32 -0800272 }
273
Christopher Ferris602b88c2017-08-04 13:04:04 -0700274 if ((g_debug->config().options() & BACKTRACE) && g_debug->config().backtrace_dump_on_exit()) {
Christopher Ferris4da25032018-03-07 13:38:48 -0800275 debug_dump_heap(android::base::StringPrintf("%s.%d.exit.txt",
276 g_debug->config().backtrace_dump_prefix().c_str(),
Christopher Ferris97b47472018-07-10 14:45:24 -0700277 getpid()).c_str());
Christopher Ferris602b88c2017-08-04 13:04:04 -0700278 }
279
Colin Cross2c759912016-02-05 16:17:39 -0800280 backtrace_shutdown();
281
Christopher Ferris63860cb2015-11-16 17:30:32 -0800282 delete g_debug;
283 g_debug = nullptr;
284
285 DebugDisableFinalize();
286}
287
Christopher Ferris4da25032018-03-07 13:38:48 -0800288void debug_get_malloc_leak_info(uint8_t** info, size_t* overall_size, size_t* info_size,
289 size_t* total_memory, size_t* backtrace_size) {
Christopher Ferris63860cb2015-11-16 17:30:32 -0800290 ScopedDisableDebugCalls disable;
291
292 // Verify the arguments.
Yi Kong32bc0fc2018-08-02 17:31:13 -0700293 if (info == nullptr || overall_size == nullptr || info_size == nullptr || total_memory == nullptr ||
Christopher Ferris4da25032018-03-07 13:38:48 -0800294 backtrace_size == nullptr) {
Christopher Ferris63860cb2015-11-16 17:30:32 -0800295 error_log("get_malloc_leak_info: At least one invalid parameter.");
296 return;
297 }
298
299 *info = nullptr;
300 *overall_size = 0;
301 *info_size = 0;
302 *total_memory = 0;
303 *backtrace_size = 0;
304
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700305 if (!(g_debug->config().options() & BACKTRACE)) {
Christopher Ferris4da25032018-03-07 13:38:48 -0800306 error_log(
307 "get_malloc_leak_info: Allocations not being tracked, to enable "
308 "set the option 'backtrace'.");
Christopher Ferris63860cb2015-11-16 17:30:32 -0800309 return;
310 }
311
Christopher Ferris4da25032018-03-07 13:38:48 -0800312 PointerData::GetInfo(info, overall_size, info_size, total_memory, backtrace_size);
Christopher Ferris63860cb2015-11-16 17:30:32 -0800313}
314
315void debug_free_malloc_leak_info(uint8_t* info) {
316 g_dispatch->free(info);
317}
318
Christopher Ferris55a89a42016-04-07 17:14:53 -0700319size_t debug_malloc_usable_size(void* pointer) {
320 if (DebugCallsDisabled() || pointer == nullptr) {
321 return g_dispatch->malloc_usable_size(pointer);
Christopher Ferris63860cb2015-11-16 17:30:32 -0800322 }
Christopher Ferris55a89a42016-04-07 17:14:53 -0700323 ScopedDisableDebugCalls disable;
Christopher Ferris63860cb2015-11-16 17:30:32 -0800324
Christopher Ferris4da25032018-03-07 13:38:48 -0800325 if (!VerifyPointer(pointer, "malloc_usable_size")) {
326 return 0;
327 }
328
329 return InternalMallocUsableSize(pointer);
Christopher Ferris55a89a42016-04-07 17:14:53 -0700330}
331
Christopher Ferris4da25032018-03-07 13:38:48 -0800332static void* InternalMalloc(size_t size) {
333 if ((g_debug->config().options() & BACKTRACE) && g_debug->pointer->ShouldDumpAndReset()) {
334 debug_dump_heap(android::base::StringPrintf(
335 "%s.%d.txt", g_debug->config().backtrace_dump_prefix().c_str(), getpid())
336 .c_str());
Christopher Ferris602b88c2017-08-04 13:04:04 -0700337 }
338
Colin Cross9567c7b2016-03-09 17:56:14 -0800339 if (size == 0) {
340 size = 1;
341 }
342
Christopher Ferris63860cb2015-11-16 17:30:32 -0800343 size_t real_size = size + g_debug->extra_bytes();
344 if (real_size < size) {
345 // Overflow.
346 errno = ENOMEM;
347 return nullptr;
348 }
349
Christopher Ferris4da25032018-03-07 13:38:48 -0800350 if (size > PointerInfoType::MaxSize()) {
351 errno = ENOMEM;
352 return nullptr;
353 }
Christopher Ferris63860cb2015-11-16 17:30:32 -0800354
Christopher Ferris4da25032018-03-07 13:38:48 -0800355 void* pointer;
356 if (g_debug->HeaderEnabled()) {
357 Header* header =
358 reinterpret_cast<Header*>(g_dispatch->memalign(MINIMUM_ALIGNMENT_BYTES, real_size));
Christopher Ferris63860cb2015-11-16 17:30:32 -0800359 if (header == nullptr) {
360 return nullptr;
361 }
362 pointer = InitHeader(header, header, size);
363 } else {
364 pointer = g_dispatch->malloc(real_size);
365 }
366
Christopher Ferris4da25032018-03-07 13:38:48 -0800367 if (pointer != nullptr) {
368 if (g_debug->TrackPointers()) {
369 PointerData::Add(pointer, size);
370 }
371
372 if (g_debug->config().options() & FILL_ON_ALLOC) {
373 size_t bytes = InternalMallocUsableSize(pointer);
374 size_t fill_bytes = g_debug->config().fill_on_alloc_bytes();
375 bytes = (bytes < fill_bytes) ? bytes : fill_bytes;
376 memset(pointer, g_debug->config().fill_alloc_value(), bytes);
377 }
Christopher Ferris63860cb2015-11-16 17:30:32 -0800378 }
379 return pointer;
380}
381
Christopher Ferris55a89a42016-04-07 17:14:53 -0700382void* debug_malloc(size_t size) {
383 if (DebugCallsDisabled()) {
384 return g_dispatch->malloc(size);
Christopher Ferris63860cb2015-11-16 17:30:32 -0800385 }
Christopher Ferris55a89a42016-04-07 17:14:53 -0700386 ScopedDisableDebugCalls disable;
Christopher Ferris63860cb2015-11-16 17:30:32 -0800387
Christopher Ferris4da25032018-03-07 13:38:48 -0800388 void* pointer = InternalMalloc(size);
Christopher Ferris7bd01782016-04-20 12:30:58 -0700389
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700390 if (g_debug->config().options() & RECORD_ALLOCS) {
Christopher Ferris7bd01782016-04-20 12:30:58 -0700391 g_debug->record->AddEntry(new MallocEntry(pointer, size));
392 }
393
394 return pointer;
Christopher Ferris55a89a42016-04-07 17:14:53 -0700395}
396
Christopher Ferris4da25032018-03-07 13:38:48 -0800397static void InternalFree(void* pointer) {
398 if ((g_debug->config().options() & BACKTRACE) && g_debug->pointer->ShouldDumpAndReset()) {
399 debug_dump_heap(android::base::StringPrintf(
400 "%s.%d.txt", g_debug->config().backtrace_dump_prefix().c_str(), getpid())
401 .c_str());
Christopher Ferris602b88c2017-08-04 13:04:04 -0700402 }
403
Christopher Ferris63860cb2015-11-16 17:30:32 -0800404 void* free_pointer = pointer;
405 size_t bytes;
Christopher Ferrisd0919622016-03-15 22:39:39 -0700406 Header* header;
Christopher Ferris4da25032018-03-07 13:38:48 -0800407 if (g_debug->HeaderEnabled()) {
Christopher Ferrisd0919622016-03-15 22:39:39 -0700408 header = g_debug->GetHeader(pointer);
Christopher Ferris63860cb2015-11-16 17:30:32 -0800409 free_pointer = header->orig_pointer;
410
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700411 if (g_debug->config().options() & FRONT_GUARD) {
Christopher Ferris55a89a42016-04-07 17:14:53 -0700412 if (!g_debug->front_guard->Valid(header)) {
413 g_debug->front_guard->LogFailure(header);
Christopher Ferris63860cb2015-11-16 17:30:32 -0800414 }
415 }
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700416 if (g_debug->config().options() & REAR_GUARD) {
Christopher Ferris55a89a42016-04-07 17:14:53 -0700417 if (!g_debug->rear_guard->Valid(header)) {
418 g_debug->rear_guard->LogFailure(header);
Christopher Ferris63860cb2015-11-16 17:30:32 -0800419 }
420 }
421
Christopher Ferris7993b802016-01-28 18:35:05 -0800422 header->tag = DEBUG_FREE_TAG;
Christopher Ferris63860cb2015-11-16 17:30:32 -0800423
424 bytes = header->usable_size;
425 } else {
426 bytes = g_dispatch->malloc_usable_size(pointer);
427 }
428
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700429 if (g_debug->config().options() & FILL_ON_FREE) {
430 size_t fill_bytes = g_debug->config().fill_on_free_bytes();
Christopher Ferris63860cb2015-11-16 17:30:32 -0800431 bytes = (bytes < fill_bytes) ? bytes : fill_bytes;
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700432 memset(pointer, g_debug->config().fill_free_value(), bytes);
Christopher Ferris63860cb2015-11-16 17:30:32 -0800433 }
434
Christopher Ferris4da25032018-03-07 13:38:48 -0800435 if (g_debug->TrackPointers()) {
436 PointerData::Remove(pointer);
437 }
438
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700439 if (g_debug->config().options() & FREE_TRACK) {
Christopher Ferrisd0919622016-03-15 22:39:39 -0700440 // Do not add the allocation until we are done modifying the pointer
441 // itself. This avoids a race if a lot of threads are all doing
442 // frees at the same time and we wind up trying to really free this
443 // pointer from another thread, while still trying to free it in
444 // this function.
Christopher Ferris4da25032018-03-07 13:38:48 -0800445 pointer = PointerData::AddFreed(pointer);
446 if (pointer != nullptr) {
447 if (g_debug->HeaderEnabled()) {
448 pointer = g_debug->GetHeader(pointer)->orig_pointer;
449 }
450 g_dispatch->free(pointer);
451 }
Christopher Ferrisd0919622016-03-15 22:39:39 -0700452 } else {
453 g_dispatch->free(free_pointer);
454 }
Christopher Ferris63860cb2015-11-16 17:30:32 -0800455}
456
Christopher Ferris55a89a42016-04-07 17:14:53 -0700457void debug_free(void* pointer) {
458 if (DebugCallsDisabled() || pointer == nullptr) {
459 return g_dispatch->free(pointer);
460 }
461 ScopedDisableDebugCalls disable;
462
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700463 if (g_debug->config().options() & RECORD_ALLOCS) {
Christopher Ferris7bd01782016-04-20 12:30:58 -0700464 g_debug->record->AddEntry(new FreeEntry(pointer));
465 }
466
Christopher Ferris4da25032018-03-07 13:38:48 -0800467 if (!VerifyPointer(pointer, "free")) {
468 return;
469 }
470
471 InternalFree(pointer);
Christopher Ferris55a89a42016-04-07 17:14:53 -0700472}
473
Christopher Ferris63860cb2015-11-16 17:30:32 -0800474void* debug_memalign(size_t alignment, size_t bytes) {
475 if (DebugCallsDisabled()) {
476 return g_dispatch->memalign(alignment, bytes);
477 }
Christopher Ferris55a89a42016-04-07 17:14:53 -0700478 ScopedDisableDebugCalls disable;
Christopher Ferris63860cb2015-11-16 17:30:32 -0800479
Colin Cross9567c7b2016-03-09 17:56:14 -0800480 if (bytes == 0) {
481 bytes = 1;
482 }
483
Christopher Ferris4da25032018-03-07 13:38:48 -0800484 if (bytes > PointerInfoType::MaxSize()) {
485 errno = ENOMEM;
486 return nullptr;
487 }
Christopher Ferris63860cb2015-11-16 17:30:32 -0800488
Christopher Ferris4da25032018-03-07 13:38:48 -0800489 void* pointer;
490 if (g_debug->HeaderEnabled()) {
Christopher Ferris63860cb2015-11-16 17:30:32 -0800491 // Make the alignment a power of two.
492 if (!powerof2(alignment)) {
493 alignment = BIONIC_ROUND_UP_POWER_OF_2(alignment);
494 }
Christopher Ferris72df6702016-02-11 15:51:31 -0800495 // Force the alignment to at least MINIMUM_ALIGNMENT_BYTES to guarantee
Christopher Ferris63860cb2015-11-16 17:30:32 -0800496 // that the header is aligned properly.
Christopher Ferris72df6702016-02-11 15:51:31 -0800497 if (alignment < MINIMUM_ALIGNMENT_BYTES) {
498 alignment = MINIMUM_ALIGNMENT_BYTES;
Christopher Ferris63860cb2015-11-16 17:30:32 -0800499 }
500
501 // We don't have any idea what the natural alignment of
502 // the underlying native allocator is, so we always need to
503 // over allocate.
504 size_t real_size = alignment + bytes + g_debug->extra_bytes();
505 if (real_size < bytes) {
506 // Overflow.
507 errno = ENOMEM;
508 return nullptr;
509 }
510
511 pointer = g_dispatch->malloc(real_size);
512 if (pointer == nullptr) {
513 return nullptr;
514 }
515
516 uintptr_t value = reinterpret_cast<uintptr_t>(pointer) + g_debug->pointer_offset();
517 // Now align the pointer.
518 value += (-value % alignment);
519
520 Header* header = g_debug->GetHeader(reinterpret_cast<void*>(value));
521 pointer = InitHeader(header, pointer, bytes);
522 } else {
523 size_t real_size = bytes + g_debug->extra_bytes();
524 if (real_size < bytes) {
525 // Overflow.
526 errno = ENOMEM;
527 return nullptr;
528 }
529 pointer = g_dispatch->memalign(alignment, real_size);
530 }
531
Christopher Ferris4da25032018-03-07 13:38:48 -0800532 if (pointer != nullptr) {
533 if (g_debug->TrackPointers()) {
534 PointerData::Add(pointer, bytes);
535 }
Christopher Ferris55a89a42016-04-07 17:14:53 -0700536
Christopher Ferris4da25032018-03-07 13:38:48 -0800537 if (g_debug->config().options() & FILL_ON_ALLOC) {
538 size_t bytes = InternalMallocUsableSize(pointer);
539 size_t fill_bytes = g_debug->config().fill_on_alloc_bytes();
540 bytes = (bytes < fill_bytes) ? bytes : fill_bytes;
541 memset(pointer, g_debug->config().fill_alloc_value(), bytes);
542 }
543
544 if (g_debug->config().options() & RECORD_ALLOCS) {
545 g_debug->record->AddEntry(new MemalignEntry(pointer, bytes, alignment));
546 }
Christopher Ferris7bd01782016-04-20 12:30:58 -0700547 }
548
Christopher Ferris63860cb2015-11-16 17:30:32 -0800549 return pointer;
550}
551
552void* debug_realloc(void* pointer, size_t bytes) {
553 if (DebugCallsDisabled()) {
554 return g_dispatch->realloc(pointer, bytes);
555 }
Christopher Ferris55a89a42016-04-07 17:14:53 -0700556 ScopedDisableDebugCalls disable;
Christopher Ferris63860cb2015-11-16 17:30:32 -0800557
558 if (pointer == nullptr) {
Christopher Ferris4da25032018-03-07 13:38:48 -0800559 pointer = InternalMalloc(bytes);
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700560 if (g_debug->config().options() & RECORD_ALLOCS) {
Christopher Ferris7bd01782016-04-20 12:30:58 -0700561 g_debug->record->AddEntry(new ReallocEntry(pointer, bytes, nullptr));
562 }
563 return pointer;
Christopher Ferris63860cb2015-11-16 17:30:32 -0800564 }
565
Christopher Ferris4da25032018-03-07 13:38:48 -0800566 if (!VerifyPointer(pointer, "realloc")) {
567 return nullptr;
568 }
569
Christopher Ferris63860cb2015-11-16 17:30:32 -0800570 if (bytes == 0) {
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700571 if (g_debug->config().options() & RECORD_ALLOCS) {
Christopher Ferris7bd01782016-04-20 12:30:58 -0700572 g_debug->record->AddEntry(new ReallocEntry(nullptr, bytes, pointer));
573 }
574
Christopher Ferris4da25032018-03-07 13:38:48 -0800575 InternalFree(pointer);
Christopher Ferris63860cb2015-11-16 17:30:32 -0800576 return nullptr;
577 }
578
579 size_t real_size = bytes;
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700580 if (g_debug->config().options() & EXPAND_ALLOC) {
581 real_size += g_debug->config().expand_alloc_bytes();
Christopher Ferris63860cb2015-11-16 17:30:32 -0800582 if (real_size < bytes) {
583 // Overflow.
584 errno = ENOMEM;
585 return nullptr;
586 }
587 }
588
Christopher Ferris4da25032018-03-07 13:38:48 -0800589 if (bytes > PointerInfoType::MaxSize()) {
590 errno = ENOMEM;
591 return nullptr;
592 }
593
Christopher Ferris63860cb2015-11-16 17:30:32 -0800594 void* new_pointer;
595 size_t prev_size;
Christopher Ferris4da25032018-03-07 13:38:48 -0800596 if (g_debug->HeaderEnabled()) {
Christopher Ferris63860cb2015-11-16 17:30:32 -0800597 // Same size, do nothing.
Christopher Ferris4da25032018-03-07 13:38:48 -0800598 Header* header = g_debug->GetHeader(pointer);
599 if (real_size == header->size) {
600 if (g_debug->TrackPointers()) {
601 // Remove and re-add so that the backtrace is updated.
602 PointerData::Remove(pointer);
603 PointerData::Add(pointer, real_size);
604 }
Christopher Ferris63860cb2015-11-16 17:30:32 -0800605 return pointer;
606 }
607
608 // Allocation is shrinking.
609 if (real_size < header->usable_size) {
610 header->size = real_size;
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700611 if (g_debug->config().options() & REAR_GUARD) {
Christopher Ferris63860cb2015-11-16 17:30:32 -0800612 // Don't bother allocating a smaller pointer in this case, simply
613 // change the header usable_size and reset the rear guard.
Christopher Ferris4da25032018-03-07 13:38:48 -0800614 header->usable_size = header->size;
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700615 memset(g_debug->GetRearGuard(header), g_debug->config().rear_guard_value(),
616 g_debug->config().rear_guard_bytes());
Christopher Ferris63860cb2015-11-16 17:30:32 -0800617 }
Christopher Ferris4da25032018-03-07 13:38:48 -0800618 if (g_debug->TrackPointers()) {
619 // Remove and re-add so that the backtrace is updated.
620 PointerData::Remove(pointer);
621 PointerData::Add(pointer, real_size);
622 }
Christopher Ferris63860cb2015-11-16 17:30:32 -0800623 return pointer;
624 }
625
626 // Allocate the new size.
Christopher Ferris4da25032018-03-07 13:38:48 -0800627 new_pointer = InternalMalloc(bytes);
Christopher Ferris63860cb2015-11-16 17:30:32 -0800628 if (new_pointer == nullptr) {
629 errno = ENOMEM;
630 return nullptr;
631 }
632
633 prev_size = header->usable_size;
634 memcpy(new_pointer, pointer, prev_size);
Christopher Ferris4da25032018-03-07 13:38:48 -0800635 InternalFree(pointer);
Christopher Ferris63860cb2015-11-16 17:30:32 -0800636 } else {
Christopher Ferris4da25032018-03-07 13:38:48 -0800637 if (g_debug->TrackPointers()) {
638 PointerData::Remove(pointer);
639 }
640
Christopher Ferris63860cb2015-11-16 17:30:32 -0800641 prev_size = g_dispatch->malloc_usable_size(pointer);
642 new_pointer = g_dispatch->realloc(pointer, real_size);
643 if (new_pointer == nullptr) {
644 return nullptr;
645 }
Christopher Ferris4da25032018-03-07 13:38:48 -0800646
647 if (g_debug->TrackPointers()) {
648 PointerData::Add(new_pointer, real_size);
649 }
Christopher Ferris63860cb2015-11-16 17:30:32 -0800650 }
651
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700652 if (g_debug->config().options() & FILL_ON_ALLOC) {
Christopher Ferris4da25032018-03-07 13:38:48 -0800653 size_t bytes = InternalMallocUsableSize(new_pointer);
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700654 if (bytes > g_debug->config().fill_on_alloc_bytes()) {
655 bytes = g_debug->config().fill_on_alloc_bytes();
Christopher Ferris63860cb2015-11-16 17:30:32 -0800656 }
657 if (bytes > prev_size) {
658 memset(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(new_pointer) + prev_size),
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700659 g_debug->config().fill_alloc_value(), bytes - prev_size);
Christopher Ferris63860cb2015-11-16 17:30:32 -0800660 }
661 }
662
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700663 if (g_debug->config().options() & RECORD_ALLOCS) {
Christopher Ferris7bd01782016-04-20 12:30:58 -0700664 g_debug->record->AddEntry(new ReallocEntry(new_pointer, bytes, pointer));
665 }
666
Christopher Ferris63860cb2015-11-16 17:30:32 -0800667 return new_pointer;
668}
669
670void* debug_calloc(size_t nmemb, size_t bytes) {
671 if (DebugCallsDisabled()) {
672 return g_dispatch->calloc(nmemb, bytes);
673 }
Christopher Ferris55a89a42016-04-07 17:14:53 -0700674 ScopedDisableDebugCalls disable;
Christopher Ferris63860cb2015-11-16 17:30:32 -0800675
Colin Cross7877df62016-03-10 13:01:27 -0800676 size_t size;
677 if (__builtin_mul_overflow(nmemb, bytes, &size)) {
678 // Overflow
679 errno = ENOMEM;
680 return nullptr;
681 }
682
Colin Cross9567c7b2016-03-09 17:56:14 -0800683 if (size == 0) {
684 size = 1;
685 }
686
Colin Cross7877df62016-03-10 13:01:27 -0800687 size_t real_size;
688 if (__builtin_add_overflow(size, g_debug->extra_bytes(), &real_size)) {
Christopher Ferris63860cb2015-11-16 17:30:32 -0800689 // Overflow.
690 errno = ENOMEM;
691 return nullptr;
692 }
693
Christopher Ferris4da25032018-03-07 13:38:48 -0800694 if (real_size > PointerInfoType::MaxSize()) {
695 errno = ENOMEM;
696 return nullptr;
697 }
Christopher Ferris63860cb2015-11-16 17:30:32 -0800698
Christopher Ferris4da25032018-03-07 13:38:48 -0800699 void* pointer;
700 if (g_debug->HeaderEnabled()) {
Christopher Ferris63860cb2015-11-16 17:30:32 -0800701 // Need to guarantee the alignment of the header.
Christopher Ferris4da25032018-03-07 13:38:48 -0800702 Header* header =
703 reinterpret_cast<Header*>(g_dispatch->memalign(MINIMUM_ALIGNMENT_BYTES, real_size));
Christopher Ferris63860cb2015-11-16 17:30:32 -0800704 if (header == nullptr) {
705 return nullptr;
706 }
707 memset(header, 0, g_dispatch->malloc_usable_size(header));
Christopher Ferris7bd01782016-04-20 12:30:58 -0700708 pointer = InitHeader(header, header, size);
Christopher Ferris63860cb2015-11-16 17:30:32 -0800709 } else {
Christopher Ferris7bd01782016-04-20 12:30:58 -0700710 pointer = g_dispatch->calloc(1, real_size);
Christopher Ferris63860cb2015-11-16 17:30:32 -0800711 }
Christopher Ferris4da25032018-03-07 13:38:48 -0800712
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700713 if (g_debug->config().options() & RECORD_ALLOCS) {
Christopher Ferris7bd01782016-04-20 12:30:58 -0700714 g_debug->record->AddEntry(new CallocEntry(pointer, bytes, nmemb));
715 }
Christopher Ferris4da25032018-03-07 13:38:48 -0800716
717 if (pointer != nullptr && g_debug->TrackPointers()) {
718 PointerData::Add(pointer, size);
719 }
Christopher Ferris7bd01782016-04-20 12:30:58 -0700720 return pointer;
Christopher Ferris63860cb2015-11-16 17:30:32 -0800721}
722
723struct mallinfo debug_mallinfo() {
724 return g_dispatch->mallinfo();
725}
726
Christopher Ferrisa1c0d2f2017-05-15 15:50:19 -0700727int debug_mallopt(int param, int value) {
728 return g_dispatch->mallopt(param, value);
729}
730
Christopher Ferris6c619a02019-03-01 17:59:51 -0800731int debug_malloc_info(int options, FILE* fp) {
732 if (DebugCallsDisabled() || !g_debug->TrackPointers()) {
733 return g_dispatch->malloc_info(options, fp);
734 }
735
736 MallocXmlElem root(fp, "malloc", "version=\"debug-malloc-1\"");
737 std::vector<ListInfoType> list;
738 PointerData::GetAllocList(&list);
739
740 size_t alloc_num = 0;
741 for (size_t i = 0; i < list.size(); i++) {
742 MallocXmlElem alloc(fp, "allocation", "nr=\"%zu\"", alloc_num);
743
744 size_t total = 1;
745 size_t size = list[i].size;
746 while (i < list.size() - 1 && list[i + 1].size == size) {
747 i++;
748 total++;
749 }
750 MallocXmlElem(fp, "size").Contents("%zu", list[i].size);
751 MallocXmlElem(fp, "total").Contents("%zu", total);
752 alloc_num++;
753 }
754 return 0;
755}
756
Christopher Ferriscae21a92018-02-05 18:14:55 -0800757void* debug_aligned_alloc(size_t alignment, size_t size) {
758 if (DebugCallsDisabled()) {
759 return g_dispatch->aligned_alloc(alignment, size);
760 }
Christopher Ferrisa22f5d52019-03-01 16:40:59 -0800761 if (!powerof2(alignment) || (size % alignment) != 0) {
Christopher Ferriscae21a92018-02-05 18:14:55 -0800762 errno = EINVAL;
763 return nullptr;
764 }
765 return debug_memalign(alignment, size);
766}
767
Christopher Ferris63860cb2015-11-16 17:30:32 -0800768int debug_posix_memalign(void** memptr, size_t alignment, size_t size) {
769 if (DebugCallsDisabled()) {
770 return g_dispatch->posix_memalign(memptr, alignment, size);
771 }
772
Christopher Ferris6c619a02019-03-01 17:59:51 -0800773 if (alignment < sizeof(void*) || !powerof2(alignment)) {
Christopher Ferris63860cb2015-11-16 17:30:32 -0800774 return EINVAL;
775 }
776 int saved_errno = errno;
777 *memptr = debug_memalign(alignment, size);
778 errno = saved_errno;
779 return (*memptr != nullptr) ? 0 : ENOMEM;
780}
781
Christopher Ferris4da25032018-03-07 13:38:48 -0800782int debug_iterate(uintptr_t base, size_t size, void (*callback)(uintptr_t, size_t, void*),
783 void* arg) {
784 if (g_debug->TrackPointers()) {
785 // Since malloc is disabled, don't bother acquiring any locks.
786 for (auto it = PointerData::begin(); it != PointerData::end(); ++it) {
787 callback(it->first, InternalMallocUsableSize(reinterpret_cast<void*>(it->first)), arg);
788 }
789 return 0;
790 }
Colin Cross869691c2016-01-29 12:48:18 -0800791
Christopher Ferris4da25032018-03-07 13:38:48 -0800792 // An option that adds a header will add pointer tracking, so no need to
793 // check if headers are enabled.
794 return g_dispatch->iterate(base, size, callback, arg);
Colin Cross869691c2016-01-29 12:48:18 -0800795}
796
797void debug_malloc_disable() {
798 g_dispatch->malloc_disable();
Christopher Ferris4da25032018-03-07 13:38:48 -0800799 if (g_debug->pointer) {
800 g_debug->pointer->PrepareFork();
Colin Cross869691c2016-01-29 12:48:18 -0800801 }
802}
803
804void debug_malloc_enable() {
Christopher Ferris4da25032018-03-07 13:38:48 -0800805 if (g_debug->pointer) {
806 g_debug->pointer->PostForkParent();
Colin Cross869691c2016-01-29 12:48:18 -0800807 }
808 g_dispatch->malloc_enable();
809}
810
Christopher Ferris4da25032018-03-07 13:38:48 -0800811ssize_t debug_malloc_backtrace(void* pointer, uintptr_t* frames, size_t max_frames) {
Colin Cross2d4721c2016-02-02 11:57:54 -0800812 if (DebugCallsDisabled() || pointer == nullptr) {
813 return 0;
814 }
Christopher Ferris55a89a42016-04-07 17:14:53 -0700815 ScopedDisableDebugCalls disable;
Colin Cross2d4721c2016-02-02 11:57:54 -0800816
Christopher Ferris4da25032018-03-07 13:38:48 -0800817 if (!(g_debug->config().options() & BACKTRACE)) {
818 return 0;
Colin Cross2d4721c2016-02-02 11:57:54 -0800819 }
Christopher Ferris4da25032018-03-07 13:38:48 -0800820 return PointerData::GetFrames(pointer, frames, max_frames);
Colin Cross2d4721c2016-02-02 11:57:54 -0800821}
822
Christopher Ferris63860cb2015-11-16 17:30:32 -0800823#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
824void* debug_pvalloc(size_t bytes) {
825 if (DebugCallsDisabled()) {
826 return g_dispatch->pvalloc(bytes);
827 }
828
829 size_t pagesize = getpagesize();
Dan Alberta613d0d2017-10-05 16:39:33 -0700830 size_t size = __BIONIC_ALIGN(bytes, pagesize);
Christopher Ferris63860cb2015-11-16 17:30:32 -0800831 if (size < bytes) {
832 // Overflow
833 errno = ENOMEM;
834 return nullptr;
835 }
836 return debug_memalign(pagesize, size);
837}
838
839void* debug_valloc(size_t size) {
840 if (DebugCallsDisabled()) {
841 return g_dispatch->valloc(size);
842 }
843 return debug_memalign(getpagesize(), size);
844}
845#endif
Christopher Ferris602b88c2017-08-04 13:04:04 -0700846
847static std::mutex g_dump_lock;
848
Christopher Ferris2e1a40a2018-06-13 10:46:34 -0700849static void write_dump(FILE* fp) {
850 fprintf(fp, "Android Native Heap Dump v1.2\n\n");
Christopher Ferris602b88c2017-08-04 13:04:04 -0700851
Christopher Ferris2e1a40a2018-06-13 10:46:34 -0700852 std::string fingerprint = android::base::GetProperty("ro.build.fingerprint", "unknown");
853 fprintf(fp, "Build fingerprint: '%s'\n\n", fingerprint.c_str());
Christopher Ferris602b88c2017-08-04 13:04:04 -0700854
Christopher Ferris4da25032018-03-07 13:38:48 -0800855 PointerData::DumpLiveToFile(fp);
Christopher Ferris602b88c2017-08-04 13:04:04 -0700856
857 fprintf(fp, "MAPS\n");
858 std::string content;
859 if (!android::base::ReadFileToString("/proc/self/maps", &content)) {
860 fprintf(fp, "Could not open /proc/self/maps\n");
861 } else {
862 fprintf(fp, "%s", content.c_str());
863 }
864 fprintf(fp, "END\n");
Christopher Ferris2e1a40a2018-06-13 10:46:34 -0700865}
866
867bool debug_write_malloc_leak_info(FILE* fp) {
868 ScopedDisableDebugCalls disable;
869
870 std::lock_guard<std::mutex> guard(g_dump_lock);
871
872 if (!(g_debug->config().options() & BACKTRACE)) {
873 return false;
874 }
875
876 write_dump(fp);
Christopher Ferris602b88c2017-08-04 13:04:04 -0700877 return true;
878}
Christopher Ferris2e1a40a2018-06-13 10:46:34 -0700879
880void debug_dump_heap(const char* file_name) {
881 ScopedDisableDebugCalls disable;
882
883 std::lock_guard<std::mutex> guard(g_dump_lock);
884
885 FILE* fp = fopen(file_name, "w+e");
886 if (fp == nullptr) {
887 error_log("Unable to create file: %s", file_name);
888 return;
889 }
890
891 error_log("Dumping to file: %s\n", file_name);
892 write_dump(fp);
893 fclose(fp);
894}