blob: 6eaac7de8ee82a9443ca738a826221b6911fa7ec [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 Ferrisd269fcc2019-05-06 19:03:59 -070032#include <pthread.h>
Christopher Ferris6c619a02019-03-01 17:59:51 -080033#include <stdio.h>
Christopher Ferrisc328e442019-04-01 19:31:26 -070034#include <stdlib.h>
Christopher Ferris63860cb2015-11-16 17:30:32 -080035#include <string.h>
36#include <sys/cdefs.h>
37#include <sys/param.h>
38#include <unistd.h>
39
Christopher Ferris602b88c2017-08-04 13:04:04 -070040#include <mutex>
Christopher Ferris63860cb2015-11-16 17:30:32 -080041#include <vector>
42
Christopher Ferris602b88c2017-08-04 13:04:04 -070043#include <android-base/file.h>
Christopher Ferris2e1a40a2018-06-13 10:46:34 -070044#include <android-base/properties.h>
Christopher Ferris602b88c2017-08-04 13:04:04 -070045#include <android-base/stringprintf.h>
Mitch Phillips3b21ada2020-01-07 15:47:47 -080046#include <bionic/malloc_tagged_pointers.h>
Christopher Ferris63860cb2015-11-16 17:30:32 -080047#include <private/bionic_malloc_dispatch.h>
Christopher Ferris6c619a02019-03-01 17:59:51 -080048#include <private/MallocXmlElem.h>
Christopher Ferris63860cb2015-11-16 17:30:32 -080049
Christopher Ferris72df6702016-02-11 15:51:31 -080050#include "Config.h"
Christopher Ferris63860cb2015-11-16 17:30:32 -080051#include "DebugData.h"
Christopher Ferris4da25032018-03-07 13:38:48 -080052#include "backtrace.h"
Christopher Ferris63860cb2015-11-16 17:30:32 -080053#include "debug_disable.h"
54#include "debug_log.h"
55#include "malloc_debug.h"
Christopher Ferris93bdd6a2018-04-05 11:12:38 -070056#include "UnwindBacktrace.h"
Christopher Ferris63860cb2015-11-16 17:30:32 -080057
58// ------------------------------------------------------------------------
59// Global Data
60// ------------------------------------------------------------------------
61DebugData* g_debug;
62
Christopher Ferris8189e772019-04-09 16:37:23 -070063bool* g_zygote_child;
Christopher Ferris63860cb2015-11-16 17:30:32 -080064
65const MallocDispatch* g_dispatch;
66// ------------------------------------------------------------------------
67
68// ------------------------------------------------------------------------
69// Use C style prototypes for all exported functions. This makes it easy
70// to do dlsym lookups during libc initialization when malloc debug
71// is enabled.
72// ------------------------------------------------------------------------
73__BEGIN_DECLS
74
Christopher Ferris8189e772019-04-09 16:37:23 -070075bool debug_initialize(const MallocDispatch* malloc_dispatch, bool* malloc_zygote_child,
Christopher Ferris4da25032018-03-07 13:38:48 -080076 const char* options);
Christopher Ferris63860cb2015-11-16 17:30:32 -080077void debug_finalize();
Christopher Ferris2e1a40a2018-06-13 10:46:34 -070078void debug_dump_heap(const char* file_name);
Christopher Ferris4da25032018-03-07 13:38:48 -080079void debug_get_malloc_leak_info(uint8_t** info, size_t* overall_size, size_t* info_size,
80 size_t* total_memory, size_t* backtrace_size);
Christopher Ferris2e1a40a2018-06-13 10:46:34 -070081bool debug_write_malloc_leak_info(FILE* fp);
Colin Cross2d4721c2016-02-02 11:57:54 -080082ssize_t debug_malloc_backtrace(void* pointer, uintptr_t* frames, size_t frame_count);
Christopher Ferris63860cb2015-11-16 17:30:32 -080083void debug_free_malloc_leak_info(uint8_t* info);
84size_t debug_malloc_usable_size(void* pointer);
85void* debug_malloc(size_t size);
86void debug_free(void* pointer);
Christopher Ferriscae21a92018-02-05 18:14:55 -080087void* debug_aligned_alloc(size_t alignment, size_t size);
Christopher Ferris63860cb2015-11-16 17:30:32 -080088void* debug_memalign(size_t alignment, size_t bytes);
89void* debug_realloc(void* pointer, size_t bytes);
90void* debug_calloc(size_t nmemb, size_t bytes);
91struct mallinfo debug_mallinfo();
Christopher Ferrisa1c0d2f2017-05-15 15:50:19 -070092int debug_mallopt(int param, int value);
Christopher Ferris6c619a02019-03-01 17:59:51 -080093int debug_malloc_info(int options, FILE* fp);
Christopher Ferris63860cb2015-11-16 17:30:32 -080094int debug_posix_memalign(void** memptr, size_t alignment, size_t size);
Christopher Ferris6f517cd2019-11-08 11:28:38 -080095int debug_malloc_iterate(uintptr_t base, size_t size,
96 void (*callback)(uintptr_t base, size_t size, void* arg), void* arg);
Colin Cross869691c2016-01-29 12:48:18 -080097void debug_malloc_disable();
98void debug_malloc_enable();
Christopher Ferris63860cb2015-11-16 17:30:32 -080099
100#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
101void* debug_pvalloc(size_t bytes);
102void* debug_valloc(size_t size);
103#endif
104
105__END_DECLS
106// ------------------------------------------------------------------------
107
Christopher Ferrisd269fcc2019-05-06 19:03:59 -0700108class ScopedConcurrentLock {
109 public:
110 ScopedConcurrentLock() {
111 pthread_rwlock_rdlock(&lock_);
112 }
113 ~ScopedConcurrentLock() {
114 pthread_rwlock_unlock(&lock_);
115 }
116
117 static void Init() {
118 pthread_rwlockattr_t attr;
119 // Set the attribute so that when a write lock is pending, read locks are no
120 // longer granted.
121 pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP);
122 pthread_rwlock_init(&lock_, &attr);
123 }
124
125 static void BlockAllOperations() {
126 pthread_rwlock_wrlock(&lock_);
127 }
128
129 private:
130 static pthread_rwlock_t lock_;
131};
132pthread_rwlock_t ScopedConcurrentLock::lock_;
133
Colin Cross7a28a3c2016-02-07 22:51:15 -0800134static void InitAtfork() {
135 static pthread_once_t atfork_init = PTHREAD_ONCE_INIT;
Christopher Ferris4da25032018-03-07 13:38:48 -0800136 pthread_once(&atfork_init, []() {
Colin Cross7a28a3c2016-02-07 22:51:15 -0800137 pthread_atfork(
Christopher Ferris4da25032018-03-07 13:38:48 -0800138 []() {
Colin Cross7a28a3c2016-02-07 22:51:15 -0800139 if (g_debug != nullptr) {
140 g_debug->PrepareFork();
141 }
142 },
Christopher Ferris4da25032018-03-07 13:38:48 -0800143 []() {
Colin Cross7a28a3c2016-02-07 22:51:15 -0800144 if (g_debug != nullptr) {
145 g_debug->PostForkParent();
146 }
147 },
Christopher Ferris4da25032018-03-07 13:38:48 -0800148 []() {
Colin Cross7a28a3c2016-02-07 22:51:15 -0800149 if (g_debug != nullptr) {
150 g_debug->PostForkChild();
151 }
Christopher Ferris4da25032018-03-07 13:38:48 -0800152 });
Colin Cross7a28a3c2016-02-07 22:51:15 -0800153 });
154}
Christopher Ferrisd0919622016-03-15 22:39:39 -0700155
Christopher Ferris93bdd6a2018-04-05 11:12:38 -0700156void BacktraceAndLog() {
157 if (g_debug->config().options() & BACKTRACE_FULL) {
158 std::vector<uintptr_t> frames;
159 std::vector<unwindstack::LocalFrameData> frames_info;
160 if (!Unwind(&frames, &frames_info, 256)) {
161 error_log(" Backtrace failed to get any frames.");
162 } else {
163 UnwindLog(frames_info);
164 }
165 } else {
166 std::vector<uintptr_t> frames(256);
167 size_t num_frames = backtrace_get(frames.data(), frames.size());
168 if (num_frames == 0) {
169 error_log(" Backtrace failed to get any frames.");
170 } else {
171 backtrace_log(frames.data(), num_frames);
172 }
173 }
174}
175
Christopher Ferris4da25032018-03-07 13:38:48 -0800176static void LogError(const void* pointer, const char* error_str) {
Christopher Ferris63860cb2015-11-16 17:30:32 -0800177 error_log(LOG_DIVIDER);
Christopher Ferris4da25032018-03-07 13:38:48 -0800178 error_log("+++ ALLOCATION %p %s", pointer, error_str);
179
180 // If we are tracking already freed pointers, check to see if this is
181 // one so we can print extra information.
182 if (g_debug->config().options() & FREE_TRACK) {
183 PointerData::LogFreeBacktrace(pointer);
Christopher Ferris7993b802016-01-28 18:35:05 -0800184 }
Christopher Ferris4da25032018-03-07 13:38:48 -0800185
Christopher Ferris93bdd6a2018-04-05 11:12:38 -0700186 error_log("Backtrace at time of failure:");
187 BacktraceAndLog();
Christopher Ferris63860cb2015-11-16 17:30:32 -0800188 error_log(LOG_DIVIDER);
Iris Chang7f209a92019-01-16 11:17:15 +0800189 if (g_debug->config().options() & ABORT_ON_ERROR) {
190 abort();
191 }
Christopher Ferris63860cb2015-11-16 17:30:32 -0800192}
193
Christopher Ferris4da25032018-03-07 13:38:48 -0800194static bool VerifyPointer(const void* pointer, const char* function_name) {
195 if (g_debug->HeaderEnabled()) {
196 Header* header = g_debug->GetHeader(pointer);
197 if (header->tag != DEBUG_TAG) {
198 std::string error_str;
199 if (header->tag == DEBUG_FREE_TAG) {
200 error_str = std::string("USED AFTER FREE (") + function_name + ")";
201 } else {
202 error_str = android::base::StringPrintf("HAS INVALID TAG %" PRIx32 " (%s)", header->tag,
203 function_name);
204 }
205 LogError(pointer, error_str.c_str());
206 return false;
207 }
208 }
209
210 if (g_debug->TrackPointers()) {
211 if (!PointerData::Exists(pointer)) {
212 std::string error_str(std::string("UNKNOWN POINTER (") + function_name + ")");
213 LogError(pointer, error_str.c_str());
214 return false;
215 }
216 }
217 return true;
218}
219
220static size_t InternalMallocUsableSize(void* pointer) {
221 if (g_debug->HeaderEnabled()) {
222 return g_debug->GetHeader(pointer)->usable_size;
223 } else {
224 return g_dispatch->malloc_usable_size(pointer);
225 }
226}
227
Christopher Ferris63860cb2015-11-16 17:30:32 -0800228static void* InitHeader(Header* header, void* orig_pointer, size_t size) {
229 header->tag = DEBUG_TAG;
230 header->orig_pointer = orig_pointer;
231 header->size = size;
Christopher Ferris63860cb2015-11-16 17:30:32 -0800232 header->usable_size = g_dispatch->malloc_usable_size(orig_pointer);
233 if (header->usable_size == 0) {
234 g_dispatch->free(orig_pointer);
235 return nullptr;
236 }
Christopher Ferris4da25032018-03-07 13:38:48 -0800237 header->usable_size -= g_debug->pointer_offset() + reinterpret_cast<uintptr_t>(header) -
238 reinterpret_cast<uintptr_t>(orig_pointer);
Christopher Ferris63860cb2015-11-16 17:30:32 -0800239
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700240 if (g_debug->config().options() & FRONT_GUARD) {
Christopher Ferris63860cb2015-11-16 17:30:32 -0800241 uint8_t* guard = g_debug->GetFrontGuard(header);
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700242 memset(guard, g_debug->config().front_guard_value(), g_debug->config().front_guard_bytes());
Christopher Ferris63860cb2015-11-16 17:30:32 -0800243 }
244
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700245 if (g_debug->config().options() & REAR_GUARD) {
Christopher Ferris63860cb2015-11-16 17:30:32 -0800246 uint8_t* guard = g_debug->GetRearGuard(header);
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700247 memset(guard, g_debug->config().rear_guard_value(), g_debug->config().rear_guard_bytes());
Christopher Ferris63860cb2015-11-16 17:30:32 -0800248 // If the rear guard is enabled, set the usable size to the exact size
249 // of the allocation.
Christopher Ferris4da25032018-03-07 13:38:48 -0800250 header->usable_size = header->size;
Christopher Ferris63860cb2015-11-16 17:30:32 -0800251 }
252
253 return g_debug->GetPointer(header);
254}
255
Christopher Ferris705de3c2019-05-22 13:39:57 -0700256extern "C" void __asan_init() __attribute__((weak));
257
Christopher Ferris8189e772019-04-09 16:37:23 -0700258bool debug_initialize(const MallocDispatch* malloc_dispatch, bool* zygote_child,
Christopher Ferris4da25032018-03-07 13:38:48 -0800259 const char* options) {
Christopher Ferris8189e772019-04-09 16:37:23 -0700260 if (zygote_child == nullptr || options == nullptr) {
Christopher Ferris63860cb2015-11-16 17:30:32 -0800261 return false;
262 }
Colin Cross7a28a3c2016-02-07 22:51:15 -0800263
Christopher Ferris705de3c2019-05-22 13:39:57 -0700264 if (__asan_init != 0) {
265 error_log("malloc debug cannot be enabled alongside ASAN");
266 return false;
267 }
268
Colin Cross7a28a3c2016-02-07 22:51:15 -0800269 InitAtfork();
270
Christopher Ferris8189e772019-04-09 16:37:23 -0700271 g_zygote_child = zygote_child;
Christopher Ferris63860cb2015-11-16 17:30:32 -0800272
273 g_dispatch = malloc_dispatch;
274
275 if (!DebugDisableInitialize()) {
276 return false;
277 }
278
279 DebugData* debug = new DebugData();
Tamas Berghammerac81fe82016-08-26 15:54:59 +0100280 if (!debug->Initialize(options)) {
Christopher Ferris63860cb2015-11-16 17:30:32 -0800281 delete debug;
282 DebugDisableFinalize();
283 return false;
284 }
285 g_debug = debug;
286
287 // Always enable the backtrace code since we will use it in a number
288 // of different error cases.
289 backtrace_startup();
290
Christopher Ferrisc328e442019-04-01 19:31:26 -0700291 if (g_debug->config().options() & VERBOSE) {
292 info_log("%s: malloc debug enabled", getprogname());
293 }
294
Christopher Ferrisd269fcc2019-05-06 19:03:59 -0700295 ScopedConcurrentLock::Init();
296
Christopher Ferris63860cb2015-11-16 17:30:32 -0800297 return true;
298}
299
300void debug_finalize() {
301 if (g_debug == nullptr) {
302 return;
303 }
304
Christopher Ferrisd269fcc2019-05-06 19:03:59 -0700305 // Make sure that there are no other threads doing debug allocations
306 // before we kill everything.
307 ScopedConcurrentLock::BlockAllOperations();
308
Christopher Ferris97b47472018-07-10 14:45:24 -0700309 // Turn off capturing allocations calls.
310 DebugDisableSet(true);
311
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700312 if (g_debug->config().options() & FREE_TRACK) {
Christopher Ferris4da25032018-03-07 13:38:48 -0800313 PointerData::VerifyAllFreed();
Christopher Ferris63860cb2015-11-16 17:30:32 -0800314 }
315
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700316 if (g_debug->config().options() & LEAK_TRACK) {
Christopher Ferris4da25032018-03-07 13:38:48 -0800317 PointerData::LogLeaks();
Christopher Ferris63860cb2015-11-16 17:30:32 -0800318 }
319
Christopher Ferris602b88c2017-08-04 13:04:04 -0700320 if ((g_debug->config().options() & BACKTRACE) && g_debug->config().backtrace_dump_on_exit()) {
Christopher Ferris4da25032018-03-07 13:38:48 -0800321 debug_dump_heap(android::base::StringPrintf("%s.%d.exit.txt",
322 g_debug->config().backtrace_dump_prefix().c_str(),
Christopher Ferris97b47472018-07-10 14:45:24 -0700323 getpid()).c_str());
Christopher Ferris602b88c2017-08-04 13:04:04 -0700324 }
325
Colin Cross2c759912016-02-05 16:17:39 -0800326 backtrace_shutdown();
327
Christopher Ferris63860cb2015-11-16 17:30:32 -0800328 delete g_debug;
329 g_debug = nullptr;
330
331 DebugDisableFinalize();
332}
333
Christopher Ferris4da25032018-03-07 13:38:48 -0800334void debug_get_malloc_leak_info(uint8_t** info, size_t* overall_size, size_t* info_size,
335 size_t* total_memory, size_t* backtrace_size) {
Christopher Ferrisd269fcc2019-05-06 19:03:59 -0700336 ScopedConcurrentLock lock;
337
Christopher Ferris63860cb2015-11-16 17:30:32 -0800338 ScopedDisableDebugCalls disable;
339
340 // Verify the arguments.
Yi Kong32bc0fc2018-08-02 17:31:13 -0700341 if (info == nullptr || overall_size == nullptr || info_size == nullptr || total_memory == nullptr ||
Christopher Ferris4da25032018-03-07 13:38:48 -0800342 backtrace_size == nullptr) {
Christopher Ferris63860cb2015-11-16 17:30:32 -0800343 error_log("get_malloc_leak_info: At least one invalid parameter.");
344 return;
345 }
346
347 *info = nullptr;
348 *overall_size = 0;
349 *info_size = 0;
350 *total_memory = 0;
351 *backtrace_size = 0;
352
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700353 if (!(g_debug->config().options() & BACKTRACE)) {
Christopher Ferris4da25032018-03-07 13:38:48 -0800354 error_log(
355 "get_malloc_leak_info: Allocations not being tracked, to enable "
356 "set the option 'backtrace'.");
Christopher Ferris63860cb2015-11-16 17:30:32 -0800357 return;
358 }
359
Christopher Ferris4da25032018-03-07 13:38:48 -0800360 PointerData::GetInfo(info, overall_size, info_size, total_memory, backtrace_size);
Christopher Ferris63860cb2015-11-16 17:30:32 -0800361}
362
363void debug_free_malloc_leak_info(uint8_t* info) {
364 g_dispatch->free(info);
365}
366
Christopher Ferris55a89a42016-04-07 17:14:53 -0700367size_t debug_malloc_usable_size(void* pointer) {
368 if (DebugCallsDisabled() || pointer == nullptr) {
369 return g_dispatch->malloc_usable_size(pointer);
Christopher Ferris63860cb2015-11-16 17:30:32 -0800370 }
Christopher Ferrisd269fcc2019-05-06 19:03:59 -0700371 ScopedConcurrentLock lock;
Christopher Ferris55a89a42016-04-07 17:14:53 -0700372 ScopedDisableDebugCalls disable;
Christopher Ferris63860cb2015-11-16 17:30:32 -0800373
Christopher Ferris4da25032018-03-07 13:38:48 -0800374 if (!VerifyPointer(pointer, "malloc_usable_size")) {
375 return 0;
376 }
377
378 return InternalMallocUsableSize(pointer);
Christopher Ferris55a89a42016-04-07 17:14:53 -0700379}
380
Christopher Ferris4da25032018-03-07 13:38:48 -0800381static void* InternalMalloc(size_t size) {
382 if ((g_debug->config().options() & BACKTRACE) && g_debug->pointer->ShouldDumpAndReset()) {
383 debug_dump_heap(android::base::StringPrintf(
384 "%s.%d.txt", g_debug->config().backtrace_dump_prefix().c_str(), getpid())
385 .c_str());
Christopher Ferris602b88c2017-08-04 13:04:04 -0700386 }
387
Colin Cross9567c7b2016-03-09 17:56:14 -0800388 if (size == 0) {
389 size = 1;
390 }
391
Christopher Ferris63860cb2015-11-16 17:30:32 -0800392 size_t real_size = size + g_debug->extra_bytes();
393 if (real_size < size) {
394 // Overflow.
395 errno = ENOMEM;
396 return nullptr;
397 }
398
Christopher Ferris4da25032018-03-07 13:38:48 -0800399 if (size > PointerInfoType::MaxSize()) {
400 errno = ENOMEM;
401 return nullptr;
402 }
Christopher Ferris63860cb2015-11-16 17:30:32 -0800403
Christopher Ferris4da25032018-03-07 13:38:48 -0800404 void* pointer;
405 if (g_debug->HeaderEnabled()) {
406 Header* header =
407 reinterpret_cast<Header*>(g_dispatch->memalign(MINIMUM_ALIGNMENT_BYTES, real_size));
Christopher Ferris63860cb2015-11-16 17:30:32 -0800408 if (header == nullptr) {
409 return nullptr;
410 }
411 pointer = InitHeader(header, header, size);
412 } else {
413 pointer = g_dispatch->malloc(real_size);
414 }
415
Christopher Ferris4da25032018-03-07 13:38:48 -0800416 if (pointer != nullptr) {
417 if (g_debug->TrackPointers()) {
418 PointerData::Add(pointer, size);
419 }
420
421 if (g_debug->config().options() & FILL_ON_ALLOC) {
422 size_t bytes = InternalMallocUsableSize(pointer);
423 size_t fill_bytes = g_debug->config().fill_on_alloc_bytes();
424 bytes = (bytes < fill_bytes) ? bytes : fill_bytes;
425 memset(pointer, g_debug->config().fill_alloc_value(), bytes);
426 }
Christopher Ferris63860cb2015-11-16 17:30:32 -0800427 }
428 return pointer;
429}
430
Christopher Ferris55a89a42016-04-07 17:14:53 -0700431void* debug_malloc(size_t size) {
432 if (DebugCallsDisabled()) {
433 return g_dispatch->malloc(size);
Christopher Ferris63860cb2015-11-16 17:30:32 -0800434 }
Christopher Ferrisd269fcc2019-05-06 19:03:59 -0700435 ScopedConcurrentLock lock;
Christopher Ferris55a89a42016-04-07 17:14:53 -0700436 ScopedDisableDebugCalls disable;
Christopher Ferris63860cb2015-11-16 17:30:32 -0800437
Christopher Ferris4da25032018-03-07 13:38:48 -0800438 void* pointer = InternalMalloc(size);
Christopher Ferris7bd01782016-04-20 12:30:58 -0700439
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700440 if (g_debug->config().options() & RECORD_ALLOCS) {
Christopher Ferris7bd01782016-04-20 12:30:58 -0700441 g_debug->record->AddEntry(new MallocEntry(pointer, size));
442 }
443
444 return pointer;
Christopher Ferris55a89a42016-04-07 17:14:53 -0700445}
446
Christopher Ferris4da25032018-03-07 13:38:48 -0800447static void InternalFree(void* pointer) {
448 if ((g_debug->config().options() & BACKTRACE) && g_debug->pointer->ShouldDumpAndReset()) {
449 debug_dump_heap(android::base::StringPrintf(
450 "%s.%d.txt", g_debug->config().backtrace_dump_prefix().c_str(), getpid())
451 .c_str());
Christopher Ferris602b88c2017-08-04 13:04:04 -0700452 }
453
Christopher Ferris63860cb2015-11-16 17:30:32 -0800454 void* free_pointer = pointer;
455 size_t bytes;
Christopher Ferrisd0919622016-03-15 22:39:39 -0700456 Header* header;
Christopher Ferris4da25032018-03-07 13:38:48 -0800457 if (g_debug->HeaderEnabled()) {
Christopher Ferrisd0919622016-03-15 22:39:39 -0700458 header = g_debug->GetHeader(pointer);
Christopher Ferris63860cb2015-11-16 17:30:32 -0800459 free_pointer = header->orig_pointer;
460
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700461 if (g_debug->config().options() & FRONT_GUARD) {
Christopher Ferris55a89a42016-04-07 17:14:53 -0700462 if (!g_debug->front_guard->Valid(header)) {
463 g_debug->front_guard->LogFailure(header);
Christopher Ferris63860cb2015-11-16 17:30:32 -0800464 }
465 }
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700466 if (g_debug->config().options() & REAR_GUARD) {
Christopher Ferris55a89a42016-04-07 17:14:53 -0700467 if (!g_debug->rear_guard->Valid(header)) {
468 g_debug->rear_guard->LogFailure(header);
Christopher Ferris63860cb2015-11-16 17:30:32 -0800469 }
470 }
471
Christopher Ferris7993b802016-01-28 18:35:05 -0800472 header->tag = DEBUG_FREE_TAG;
Christopher Ferris63860cb2015-11-16 17:30:32 -0800473
474 bytes = header->usable_size;
475 } else {
476 bytes = g_dispatch->malloc_usable_size(pointer);
477 }
478
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700479 if (g_debug->config().options() & FILL_ON_FREE) {
480 size_t fill_bytes = g_debug->config().fill_on_free_bytes();
Christopher Ferris63860cb2015-11-16 17:30:32 -0800481 bytes = (bytes < fill_bytes) ? bytes : fill_bytes;
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700482 memset(pointer, g_debug->config().fill_free_value(), bytes);
Christopher Ferris63860cb2015-11-16 17:30:32 -0800483 }
484
Christopher Ferris4da25032018-03-07 13:38:48 -0800485 if (g_debug->TrackPointers()) {
486 PointerData::Remove(pointer);
487 }
488
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700489 if (g_debug->config().options() & FREE_TRACK) {
Christopher Ferrisd0919622016-03-15 22:39:39 -0700490 // Do not add the allocation until we are done modifying the pointer
491 // itself. This avoids a race if a lot of threads are all doing
492 // frees at the same time and we wind up trying to really free this
493 // pointer from another thread, while still trying to free it in
494 // this function.
Christopher Ferris4da25032018-03-07 13:38:48 -0800495 pointer = PointerData::AddFreed(pointer);
496 if (pointer != nullptr) {
497 if (g_debug->HeaderEnabled()) {
498 pointer = g_debug->GetHeader(pointer)->orig_pointer;
499 }
500 g_dispatch->free(pointer);
501 }
Christopher Ferrisd0919622016-03-15 22:39:39 -0700502 } else {
503 g_dispatch->free(free_pointer);
504 }
Christopher Ferris63860cb2015-11-16 17:30:32 -0800505}
506
Christopher Ferris55a89a42016-04-07 17:14:53 -0700507void debug_free(void* pointer) {
508 if (DebugCallsDisabled() || pointer == nullptr) {
509 return g_dispatch->free(pointer);
510 }
Christopher Ferrisd269fcc2019-05-06 19:03:59 -0700511 ScopedConcurrentLock lock;
Christopher Ferris55a89a42016-04-07 17:14:53 -0700512 ScopedDisableDebugCalls disable;
513
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700514 if (g_debug->config().options() & RECORD_ALLOCS) {
Christopher Ferris7bd01782016-04-20 12:30:58 -0700515 g_debug->record->AddEntry(new FreeEntry(pointer));
516 }
517
Christopher Ferris4da25032018-03-07 13:38:48 -0800518 if (!VerifyPointer(pointer, "free")) {
519 return;
520 }
521
522 InternalFree(pointer);
Christopher Ferris55a89a42016-04-07 17:14:53 -0700523}
524
Christopher Ferris63860cb2015-11-16 17:30:32 -0800525void* debug_memalign(size_t alignment, size_t bytes) {
526 if (DebugCallsDisabled()) {
527 return g_dispatch->memalign(alignment, bytes);
528 }
Christopher Ferrisd269fcc2019-05-06 19:03:59 -0700529 ScopedConcurrentLock lock;
Christopher Ferris55a89a42016-04-07 17:14:53 -0700530 ScopedDisableDebugCalls disable;
Christopher Ferris63860cb2015-11-16 17:30:32 -0800531
Colin Cross9567c7b2016-03-09 17:56:14 -0800532 if (bytes == 0) {
533 bytes = 1;
534 }
535
Christopher Ferris4da25032018-03-07 13:38:48 -0800536 if (bytes > PointerInfoType::MaxSize()) {
537 errno = ENOMEM;
538 return nullptr;
539 }
Christopher Ferris63860cb2015-11-16 17:30:32 -0800540
Christopher Ferris4da25032018-03-07 13:38:48 -0800541 void* pointer;
542 if (g_debug->HeaderEnabled()) {
Christopher Ferris63860cb2015-11-16 17:30:32 -0800543 // Make the alignment a power of two.
544 if (!powerof2(alignment)) {
545 alignment = BIONIC_ROUND_UP_POWER_OF_2(alignment);
546 }
Christopher Ferris72df6702016-02-11 15:51:31 -0800547 // Force the alignment to at least MINIMUM_ALIGNMENT_BYTES to guarantee
Christopher Ferris63860cb2015-11-16 17:30:32 -0800548 // that the header is aligned properly.
Christopher Ferris72df6702016-02-11 15:51:31 -0800549 if (alignment < MINIMUM_ALIGNMENT_BYTES) {
550 alignment = MINIMUM_ALIGNMENT_BYTES;
Christopher Ferris63860cb2015-11-16 17:30:32 -0800551 }
552
553 // We don't have any idea what the natural alignment of
554 // the underlying native allocator is, so we always need to
555 // over allocate.
556 size_t real_size = alignment + bytes + g_debug->extra_bytes();
557 if (real_size < bytes) {
558 // Overflow.
559 errno = ENOMEM;
560 return nullptr;
561 }
562
563 pointer = g_dispatch->malloc(real_size);
564 if (pointer == nullptr) {
565 return nullptr;
566 }
567
568 uintptr_t value = reinterpret_cast<uintptr_t>(pointer) + g_debug->pointer_offset();
569 // Now align the pointer.
570 value += (-value % alignment);
571
572 Header* header = g_debug->GetHeader(reinterpret_cast<void*>(value));
573 pointer = InitHeader(header, pointer, bytes);
574 } else {
575 size_t real_size = bytes + g_debug->extra_bytes();
576 if (real_size < bytes) {
577 // Overflow.
578 errno = ENOMEM;
579 return nullptr;
580 }
581 pointer = g_dispatch->memalign(alignment, real_size);
582 }
583
Christopher Ferris4da25032018-03-07 13:38:48 -0800584 if (pointer != nullptr) {
585 if (g_debug->TrackPointers()) {
586 PointerData::Add(pointer, bytes);
587 }
Christopher Ferris55a89a42016-04-07 17:14:53 -0700588
Christopher Ferris4da25032018-03-07 13:38:48 -0800589 if (g_debug->config().options() & FILL_ON_ALLOC) {
590 size_t bytes = InternalMallocUsableSize(pointer);
591 size_t fill_bytes = g_debug->config().fill_on_alloc_bytes();
592 bytes = (bytes < fill_bytes) ? bytes : fill_bytes;
593 memset(pointer, g_debug->config().fill_alloc_value(), bytes);
594 }
595
596 if (g_debug->config().options() & RECORD_ALLOCS) {
597 g_debug->record->AddEntry(new MemalignEntry(pointer, bytes, alignment));
598 }
Christopher Ferris7bd01782016-04-20 12:30:58 -0700599 }
600
Christopher Ferris63860cb2015-11-16 17:30:32 -0800601 return pointer;
602}
603
604void* debug_realloc(void* pointer, size_t bytes) {
605 if (DebugCallsDisabled()) {
606 return g_dispatch->realloc(pointer, bytes);
607 }
Christopher Ferrisd269fcc2019-05-06 19:03:59 -0700608 ScopedConcurrentLock lock;
Christopher Ferris55a89a42016-04-07 17:14:53 -0700609 ScopedDisableDebugCalls disable;
Christopher Ferris63860cb2015-11-16 17:30:32 -0800610
611 if (pointer == nullptr) {
Christopher Ferris4da25032018-03-07 13:38:48 -0800612 pointer = InternalMalloc(bytes);
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700613 if (g_debug->config().options() & RECORD_ALLOCS) {
Christopher Ferris7bd01782016-04-20 12:30:58 -0700614 g_debug->record->AddEntry(new ReallocEntry(pointer, bytes, nullptr));
615 }
616 return pointer;
Christopher Ferris63860cb2015-11-16 17:30:32 -0800617 }
618
Christopher Ferris4da25032018-03-07 13:38:48 -0800619 if (!VerifyPointer(pointer, "realloc")) {
620 return nullptr;
621 }
622
Christopher Ferris63860cb2015-11-16 17:30:32 -0800623 if (bytes == 0) {
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700624 if (g_debug->config().options() & RECORD_ALLOCS) {
Christopher Ferris7bd01782016-04-20 12:30:58 -0700625 g_debug->record->AddEntry(new ReallocEntry(nullptr, bytes, pointer));
626 }
627
Christopher Ferris4da25032018-03-07 13:38:48 -0800628 InternalFree(pointer);
Christopher Ferris63860cb2015-11-16 17:30:32 -0800629 return nullptr;
630 }
631
632 size_t real_size = bytes;
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700633 if (g_debug->config().options() & EXPAND_ALLOC) {
634 real_size += g_debug->config().expand_alloc_bytes();
Christopher Ferris63860cb2015-11-16 17:30:32 -0800635 if (real_size < bytes) {
636 // Overflow.
637 errno = ENOMEM;
638 return nullptr;
639 }
640 }
641
Christopher Ferris4da25032018-03-07 13:38:48 -0800642 if (bytes > PointerInfoType::MaxSize()) {
643 errno = ENOMEM;
644 return nullptr;
645 }
646
Christopher Ferris63860cb2015-11-16 17:30:32 -0800647 void* new_pointer;
648 size_t prev_size;
Christopher Ferris4da25032018-03-07 13:38:48 -0800649 if (g_debug->HeaderEnabled()) {
Christopher Ferris63860cb2015-11-16 17:30:32 -0800650 // Same size, do nothing.
Christopher Ferris4da25032018-03-07 13:38:48 -0800651 Header* header = g_debug->GetHeader(pointer);
652 if (real_size == header->size) {
653 if (g_debug->TrackPointers()) {
654 // Remove and re-add so that the backtrace is updated.
655 PointerData::Remove(pointer);
656 PointerData::Add(pointer, real_size);
657 }
Christopher Ferris63860cb2015-11-16 17:30:32 -0800658 return pointer;
659 }
660
661 // Allocation is shrinking.
662 if (real_size < header->usable_size) {
663 header->size = real_size;
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700664 if (g_debug->config().options() & REAR_GUARD) {
Christopher Ferris63860cb2015-11-16 17:30:32 -0800665 // Don't bother allocating a smaller pointer in this case, simply
666 // change the header usable_size and reset the rear guard.
Christopher Ferris4da25032018-03-07 13:38:48 -0800667 header->usable_size = header->size;
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700668 memset(g_debug->GetRearGuard(header), g_debug->config().rear_guard_value(),
669 g_debug->config().rear_guard_bytes());
Christopher Ferris63860cb2015-11-16 17:30:32 -0800670 }
Christopher Ferris4da25032018-03-07 13:38:48 -0800671 if (g_debug->TrackPointers()) {
672 // Remove and re-add so that the backtrace is updated.
673 PointerData::Remove(pointer);
674 PointerData::Add(pointer, real_size);
675 }
Christopher Ferris63860cb2015-11-16 17:30:32 -0800676 return pointer;
677 }
678
679 // Allocate the new size.
Christopher Ferris4da25032018-03-07 13:38:48 -0800680 new_pointer = InternalMalloc(bytes);
Christopher Ferris63860cb2015-11-16 17:30:32 -0800681 if (new_pointer == nullptr) {
682 errno = ENOMEM;
683 return nullptr;
684 }
685
686 prev_size = header->usable_size;
687 memcpy(new_pointer, pointer, prev_size);
Christopher Ferris4da25032018-03-07 13:38:48 -0800688 InternalFree(pointer);
Christopher Ferris63860cb2015-11-16 17:30:32 -0800689 } else {
Christopher Ferris4da25032018-03-07 13:38:48 -0800690 if (g_debug->TrackPointers()) {
691 PointerData::Remove(pointer);
692 }
693
Christopher Ferris63860cb2015-11-16 17:30:32 -0800694 prev_size = g_dispatch->malloc_usable_size(pointer);
695 new_pointer = g_dispatch->realloc(pointer, real_size);
696 if (new_pointer == nullptr) {
697 return nullptr;
698 }
Christopher Ferris4da25032018-03-07 13:38:48 -0800699
700 if (g_debug->TrackPointers()) {
701 PointerData::Add(new_pointer, real_size);
702 }
Christopher Ferris63860cb2015-11-16 17:30:32 -0800703 }
704
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700705 if (g_debug->config().options() & FILL_ON_ALLOC) {
Christopher Ferris4da25032018-03-07 13:38:48 -0800706 size_t bytes = InternalMallocUsableSize(new_pointer);
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700707 if (bytes > g_debug->config().fill_on_alloc_bytes()) {
708 bytes = g_debug->config().fill_on_alloc_bytes();
Christopher Ferris63860cb2015-11-16 17:30:32 -0800709 }
710 if (bytes > prev_size) {
711 memset(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(new_pointer) + prev_size),
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700712 g_debug->config().fill_alloc_value(), bytes - prev_size);
Christopher Ferris63860cb2015-11-16 17:30:32 -0800713 }
714 }
715
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700716 if (g_debug->config().options() & RECORD_ALLOCS) {
Christopher Ferris7bd01782016-04-20 12:30:58 -0700717 g_debug->record->AddEntry(new ReallocEntry(new_pointer, bytes, pointer));
718 }
719
Christopher Ferris63860cb2015-11-16 17:30:32 -0800720 return new_pointer;
721}
722
723void* debug_calloc(size_t nmemb, size_t bytes) {
724 if (DebugCallsDisabled()) {
725 return g_dispatch->calloc(nmemb, bytes);
726 }
Christopher Ferrisd269fcc2019-05-06 19:03:59 -0700727 ScopedConcurrentLock lock;
Christopher Ferris55a89a42016-04-07 17:14:53 -0700728 ScopedDisableDebugCalls disable;
Christopher Ferris63860cb2015-11-16 17:30:32 -0800729
Colin Cross7877df62016-03-10 13:01:27 -0800730 size_t size;
731 if (__builtin_mul_overflow(nmemb, bytes, &size)) {
732 // Overflow
733 errno = ENOMEM;
734 return nullptr;
735 }
736
Colin Cross9567c7b2016-03-09 17:56:14 -0800737 if (size == 0) {
738 size = 1;
739 }
740
Colin Cross7877df62016-03-10 13:01:27 -0800741 size_t real_size;
742 if (__builtin_add_overflow(size, g_debug->extra_bytes(), &real_size)) {
Christopher Ferris63860cb2015-11-16 17:30:32 -0800743 // Overflow.
744 errno = ENOMEM;
745 return nullptr;
746 }
747
Christopher Ferris4da25032018-03-07 13:38:48 -0800748 if (real_size > PointerInfoType::MaxSize()) {
749 errno = ENOMEM;
750 return nullptr;
751 }
Christopher Ferris63860cb2015-11-16 17:30:32 -0800752
Christopher Ferris4da25032018-03-07 13:38:48 -0800753 void* pointer;
754 if (g_debug->HeaderEnabled()) {
Christopher Ferris63860cb2015-11-16 17:30:32 -0800755 // Need to guarantee the alignment of the header.
Christopher Ferris4da25032018-03-07 13:38:48 -0800756 Header* header =
757 reinterpret_cast<Header*>(g_dispatch->memalign(MINIMUM_ALIGNMENT_BYTES, real_size));
Christopher Ferris63860cb2015-11-16 17:30:32 -0800758 if (header == nullptr) {
759 return nullptr;
760 }
761 memset(header, 0, g_dispatch->malloc_usable_size(header));
Christopher Ferris7bd01782016-04-20 12:30:58 -0700762 pointer = InitHeader(header, header, size);
Christopher Ferris63860cb2015-11-16 17:30:32 -0800763 } else {
Christopher Ferris7bd01782016-04-20 12:30:58 -0700764 pointer = g_dispatch->calloc(1, real_size);
Christopher Ferris63860cb2015-11-16 17:30:32 -0800765 }
Christopher Ferris4da25032018-03-07 13:38:48 -0800766
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700767 if (g_debug->config().options() & RECORD_ALLOCS) {
Christopher Ferris7bd01782016-04-20 12:30:58 -0700768 g_debug->record->AddEntry(new CallocEntry(pointer, bytes, nmemb));
769 }
Christopher Ferris4da25032018-03-07 13:38:48 -0800770
771 if (pointer != nullptr && g_debug->TrackPointers()) {
772 PointerData::Add(pointer, size);
773 }
Christopher Ferris7bd01782016-04-20 12:30:58 -0700774 return pointer;
Christopher Ferris63860cb2015-11-16 17:30:32 -0800775}
776
777struct mallinfo debug_mallinfo() {
778 return g_dispatch->mallinfo();
779}
780
Christopher Ferrisa1c0d2f2017-05-15 15:50:19 -0700781int debug_mallopt(int param, int value) {
782 return g_dispatch->mallopt(param, value);
783}
784
Christopher Ferris6c619a02019-03-01 17:59:51 -0800785int debug_malloc_info(int options, FILE* fp) {
786 if (DebugCallsDisabled() || !g_debug->TrackPointers()) {
787 return g_dispatch->malloc_info(options, fp);
788 }
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800789
790 // Make sure any pending output is written to the file.
791 fflush(fp);
792
Christopher Ferrisd269fcc2019-05-06 19:03:59 -0700793 ScopedConcurrentLock lock;
794 ScopedDisableDebugCalls disable;
Christopher Ferris6c619a02019-03-01 17:59:51 -0800795
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800796 // Avoid any issues where allocations are made that will be freed
797 // in the fclose.
798 int fd = fileno(fp);
799 MallocXmlElem root(fd, "malloc", "version=\"debug-malloc-1\"");
Christopher Ferris6c619a02019-03-01 17:59:51 -0800800 std::vector<ListInfoType> list;
801 PointerData::GetAllocList(&list);
802
803 size_t alloc_num = 0;
804 for (size_t i = 0; i < list.size(); i++) {
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800805 MallocXmlElem alloc(fd, "allocation", "nr=\"%zu\"", alloc_num);
Christopher Ferris6c619a02019-03-01 17:59:51 -0800806
807 size_t total = 1;
808 size_t size = list[i].size;
809 while (i < list.size() - 1 && list[i + 1].size == size) {
810 i++;
811 total++;
812 }
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800813 MallocXmlElem(fd, "size").Contents("%zu", list[i].size);
814 MallocXmlElem(fd, "total").Contents("%zu", total);
Christopher Ferris6c619a02019-03-01 17:59:51 -0800815 alloc_num++;
816 }
817 return 0;
818}
819
Christopher Ferriscae21a92018-02-05 18:14:55 -0800820void* debug_aligned_alloc(size_t alignment, size_t size) {
821 if (DebugCallsDisabled()) {
822 return g_dispatch->aligned_alloc(alignment, size);
823 }
Christopher Ferrisa22f5d52019-03-01 16:40:59 -0800824 if (!powerof2(alignment) || (size % alignment) != 0) {
Christopher Ferriscae21a92018-02-05 18:14:55 -0800825 errno = EINVAL;
826 return nullptr;
827 }
828 return debug_memalign(alignment, size);
829}
830
Christopher Ferris63860cb2015-11-16 17:30:32 -0800831int debug_posix_memalign(void** memptr, size_t alignment, size_t size) {
832 if (DebugCallsDisabled()) {
833 return g_dispatch->posix_memalign(memptr, alignment, size);
834 }
835
Christopher Ferris6c619a02019-03-01 17:59:51 -0800836 if (alignment < sizeof(void*) || !powerof2(alignment)) {
Christopher Ferris63860cb2015-11-16 17:30:32 -0800837 return EINVAL;
838 }
839 int saved_errno = errno;
840 *memptr = debug_memalign(alignment, size);
841 errno = saved_errno;
842 return (*memptr != nullptr) ? 0 : ENOMEM;
843}
844
Christopher Ferris6f517cd2019-11-08 11:28:38 -0800845int debug_malloc_iterate(uintptr_t base, size_t size, void (*callback)(uintptr_t, size_t, void*),
Christopher Ferris4da25032018-03-07 13:38:48 -0800846 void* arg) {
Christopher Ferrisd269fcc2019-05-06 19:03:59 -0700847 ScopedConcurrentLock lock;
Christopher Ferris4da25032018-03-07 13:38:48 -0800848 if (g_debug->TrackPointers()) {
849 // Since malloc is disabled, don't bother acquiring any locks.
850 for (auto it = PointerData::begin(); it != PointerData::end(); ++it) {
851 callback(it->first, InternalMallocUsableSize(reinterpret_cast<void*>(it->first)), arg);
852 }
853 return 0;
854 }
Colin Cross869691c2016-01-29 12:48:18 -0800855
Christopher Ferris4da25032018-03-07 13:38:48 -0800856 // An option that adds a header will add pointer tracking, so no need to
857 // check if headers are enabled.
Christopher Ferris6f517cd2019-11-08 11:28:38 -0800858 return g_dispatch->malloc_iterate(base, size, callback, arg);
Colin Cross869691c2016-01-29 12:48:18 -0800859}
860
861void debug_malloc_disable() {
Christopher Ferrisd269fcc2019-05-06 19:03:59 -0700862 ScopedConcurrentLock lock;
Colin Cross869691c2016-01-29 12:48:18 -0800863 g_dispatch->malloc_disable();
Christopher Ferris4da25032018-03-07 13:38:48 -0800864 if (g_debug->pointer) {
865 g_debug->pointer->PrepareFork();
Colin Cross869691c2016-01-29 12:48:18 -0800866 }
867}
868
869void debug_malloc_enable() {
Christopher Ferrisd269fcc2019-05-06 19:03:59 -0700870 ScopedConcurrentLock lock;
Christopher Ferris4da25032018-03-07 13:38:48 -0800871 if (g_debug->pointer) {
872 g_debug->pointer->PostForkParent();
Colin Cross869691c2016-01-29 12:48:18 -0800873 }
874 g_dispatch->malloc_enable();
875}
876
Christopher Ferris4da25032018-03-07 13:38:48 -0800877ssize_t debug_malloc_backtrace(void* pointer, uintptr_t* frames, size_t max_frames) {
Colin Cross2d4721c2016-02-02 11:57:54 -0800878 if (DebugCallsDisabled() || pointer == nullptr) {
879 return 0;
880 }
Christopher Ferrisd269fcc2019-05-06 19:03:59 -0700881 ScopedConcurrentLock lock;
Christopher Ferris55a89a42016-04-07 17:14:53 -0700882 ScopedDisableDebugCalls disable;
Colin Cross2d4721c2016-02-02 11:57:54 -0800883
Christopher Ferris4da25032018-03-07 13:38:48 -0800884 if (!(g_debug->config().options() & BACKTRACE)) {
885 return 0;
Colin Cross2d4721c2016-02-02 11:57:54 -0800886 }
Mitch Phillips3b21ada2020-01-07 15:47:47 -0800887 pointer = UntagPointer(pointer);
Christopher Ferris4da25032018-03-07 13:38:48 -0800888 return PointerData::GetFrames(pointer, frames, max_frames);
Colin Cross2d4721c2016-02-02 11:57:54 -0800889}
890
Christopher Ferris63860cb2015-11-16 17:30:32 -0800891#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
892void* debug_pvalloc(size_t bytes) {
893 if (DebugCallsDisabled()) {
894 return g_dispatch->pvalloc(bytes);
895 }
896
897 size_t pagesize = getpagesize();
Dan Alberta613d0d2017-10-05 16:39:33 -0700898 size_t size = __BIONIC_ALIGN(bytes, pagesize);
Christopher Ferris63860cb2015-11-16 17:30:32 -0800899 if (size < bytes) {
900 // Overflow
901 errno = ENOMEM;
902 return nullptr;
903 }
904 return debug_memalign(pagesize, size);
905}
906
907void* debug_valloc(size_t size) {
908 if (DebugCallsDisabled()) {
909 return g_dispatch->valloc(size);
910 }
911 return debug_memalign(getpagesize(), size);
912}
913#endif
Christopher Ferris602b88c2017-08-04 13:04:04 -0700914
915static std::mutex g_dump_lock;
916
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800917static void write_dump(int fd) {
918 dprintf(fd, "Android Native Heap Dump v1.2\n\n");
Christopher Ferris602b88c2017-08-04 13:04:04 -0700919
Christopher Ferris2e1a40a2018-06-13 10:46:34 -0700920 std::string fingerprint = android::base::GetProperty("ro.build.fingerprint", "unknown");
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800921 dprintf(fd, "Build fingerprint: '%s'\n\n", fingerprint.c_str());
Christopher Ferris602b88c2017-08-04 13:04:04 -0700922
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800923 PointerData::DumpLiveToFile(fd);
Christopher Ferris602b88c2017-08-04 13:04:04 -0700924
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800925 dprintf(fd, "MAPS\n");
Christopher Ferris602b88c2017-08-04 13:04:04 -0700926 std::string content;
927 if (!android::base::ReadFileToString("/proc/self/maps", &content)) {
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800928 dprintf(fd, "Could not open /proc/self/maps\n");
Christopher Ferris602b88c2017-08-04 13:04:04 -0700929 } else {
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800930 dprintf(fd, "%s", content.c_str());
Christopher Ferris602b88c2017-08-04 13:04:04 -0700931 }
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800932 dprintf(fd, "END\n");
Christopher Ferris2e1a40a2018-06-13 10:46:34 -0700933}
934
935bool debug_write_malloc_leak_info(FILE* fp) {
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800936 // Make sure any pending output is written to the file.
937 fflush(fp);
938
Christopher Ferrisd269fcc2019-05-06 19:03:59 -0700939 ScopedConcurrentLock lock;
Christopher Ferris2e1a40a2018-06-13 10:46:34 -0700940 ScopedDisableDebugCalls disable;
941
942 std::lock_guard<std::mutex> guard(g_dump_lock);
943
944 if (!(g_debug->config().options() & BACKTRACE)) {
945 return false;
946 }
947
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800948 write_dump(fileno(fp));
949
Christopher Ferris602b88c2017-08-04 13:04:04 -0700950 return true;
951}
Christopher Ferris2e1a40a2018-06-13 10:46:34 -0700952
953void debug_dump_heap(const char* file_name) {
Christopher Ferrisd269fcc2019-05-06 19:03:59 -0700954 ScopedConcurrentLock lock;
Christopher Ferris2e1a40a2018-06-13 10:46:34 -0700955 ScopedDisableDebugCalls disable;
956
957 std::lock_guard<std::mutex> guard(g_dump_lock);
958
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800959 int fd = open(file_name, O_RDWR | O_CREAT | O_NOFOLLOW | O_TRUNC | O_CLOEXEC, 0644);
960 if (fd == -1) {
Christopher Ferris2e1a40a2018-06-13 10:46:34 -0700961 error_log("Unable to create file: %s", file_name);
962 return;
963 }
964
965 error_log("Dumping to file: %s\n", file_name);
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800966 write_dump(fd);
967 close(fd);
Christopher Ferris2e1a40a2018-06-13 10:46:34 -0700968}