blob: 4bc5649e22fa273b296d305c5b18102fd2b3f9f7 [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 Ferris9bf78172020-05-20 15:37:30 -070033#include <signal.h>
Christopher Ferris6c619a02019-03-01 17:59:51 -080034#include <stdio.h>
Christopher Ferrisc328e442019-04-01 19:31:26 -070035#include <stdlib.h>
Christopher Ferris63860cb2015-11-16 17:30:32 -080036#include <string.h>
37#include <sys/cdefs.h>
38#include <sys/param.h>
Christopher Ferris9bf78172020-05-20 15:37:30 -070039#include <sys/syscall.h>
Christopher Ferris63860cb2015-11-16 17:30:32 -080040#include <unistd.h>
41
Christopher Ferris602b88c2017-08-04 13:04:04 -070042#include <mutex>
Christopher Ferris63860cb2015-11-16 17:30:32 -080043#include <vector>
44
Christopher Ferris602b88c2017-08-04 13:04:04 -070045#include <android-base/file.h>
Christopher Ferris2e1a40a2018-06-13 10:46:34 -070046#include <android-base/properties.h>
Christopher Ferris602b88c2017-08-04 13:04:04 -070047#include <android-base/stringprintf.h>
Mitch Phillips3b21ada2020-01-07 15:47:47 -080048#include <bionic/malloc_tagged_pointers.h>
Christopher Ferris9bf78172020-05-20 15:37:30 -070049#include <platform/bionic/reserved_signals.h>
Christopher Ferris6c619a02019-03-01 17:59:51 -080050#include <private/MallocXmlElem.h>
Christopher Ferris9bf78172020-05-20 15:37:30 -070051#include <private/bionic_malloc_dispatch.h>
Christopher Ferris459eecb2022-01-07 13:38:10 -080052#include <unwindstack/Unwinder.h>
Christopher Ferris63860cb2015-11-16 17:30:32 -080053
Christopher Ferris72df6702016-02-11 15:51:31 -080054#include "Config.h"
Christopher Ferris63860cb2015-11-16 17:30:32 -080055#include "DebugData.h"
Christopher Ferrisb42e8b42022-05-09 14:00:47 -070056#include "Unreachable.h"
57#include "UnwindBacktrace.h"
Christopher Ferris4da25032018-03-07 13:38:48 -080058#include "backtrace.h"
Christopher Ferris63860cb2015-11-16 17:30:32 -080059#include "debug_disable.h"
60#include "debug_log.h"
61#include "malloc_debug.h"
62
63// ------------------------------------------------------------------------
64// Global Data
65// ------------------------------------------------------------------------
66DebugData* g_debug;
67
Christopher Ferris8189e772019-04-09 16:37:23 -070068bool* g_zygote_child;
Christopher Ferris63860cb2015-11-16 17:30:32 -080069
70const MallocDispatch* g_dispatch;
Chia-hung Duanf7e8b172022-11-01 21:37:56 +000071
72static __always_inline uint64_t Nanotime() {
73 struct timespec t = {};
74 clock_gettime(CLOCK_MONOTONIC, &t);
75 return static_cast<uint64_t>(t.tv_sec) * 1000000000LL + t.tv_nsec;
76}
77
78namespace {
79// A TimedResult contains the result of from malloc end_ns al. functions and the
80// start/end timestamps.
81struct TimedResult {
82 uint64_t start_ns = 0;
83 uint64_t end_ns = 0;
84 union {
85 size_t s;
86 int i;
87 void* p;
88 } v;
89
90 uint64_t GetStartTimeNS() const { return start_ns; }
91 uint64_t GetEndTimeNS() const { return end_ns; }
92 void SetStartTimeNS(uint64_t t) { start_ns = t; }
93 void SetEndTimeNS(uint64_t t) { end_ns = t; }
94
95 template <typename T>
96 void setValue(T);
97 template <>
98 void setValue(size_t s) {
99 v.s = s;
100 }
101 template <>
102 void setValue(int i) {
103 v.i = i;
104 }
105 template <>
106 void setValue(void* p) {
107 v.p = p;
108 }
109
110 template <typename T>
111 T getValue() const;
112 template <>
113 size_t getValue<size_t>() const {
114 return v.s;
115 }
116 template <>
117 int getValue<int>() const {
118 return v.i;
119 }
120 template <>
121 void* getValue<void*>() const {
122 return v.p;
123 }
124};
125
126class ScopedTimer {
127 public:
128 ScopedTimer(TimedResult& res) : res_(res) { res_.start_ns = Nanotime(); }
129
130 ~ScopedTimer() { res_.end_ns = Nanotime(); }
131
132 private:
133 TimedResult& res_;
134};
135
136} // namespace
137
138template <typename MallocFn, typename... Args>
139static TimedResult TimerCall(MallocFn fn, Args... args) {
140 TimedResult ret;
141 decltype((g_dispatch->*fn)(args...)) r;
142 if (g_debug->config().options() & RECORD_ALLOCS) {
143 ScopedTimer t(ret);
144 r = (g_dispatch->*fn)(args...);
145 } else {
146 r = (g_dispatch->*fn)(args...);
147 }
148 ret.setValue<decltype(r)>(r);
149 return ret;
150}
151
152template <typename MallocFn, typename... Args>
153static TimedResult TimerCallVoid(MallocFn fn, Args... args) {
154 TimedResult ret;
155 {
156 ScopedTimer t(ret);
157 (g_dispatch->*fn)(args...);
158 }
159 return ret;
160}
161
162#define TCALL(FUNC, ...) TimerCall(&MallocDispatch::FUNC, __VA_ARGS__);
163#define TCALLVOID(FUNC, ...) TimerCallVoid(&MallocDispatch::FUNC, __VA_ARGS__);
164
Christopher Ferris63860cb2015-11-16 17:30:32 -0800165// ------------------------------------------------------------------------
166
167// ------------------------------------------------------------------------
168// Use C style prototypes for all exported functions. This makes it easy
169// to do dlsym lookups during libc initialization when malloc debug
170// is enabled.
171// ------------------------------------------------------------------------
172__BEGIN_DECLS
173
Christopher Ferris8189e772019-04-09 16:37:23 -0700174bool debug_initialize(const MallocDispatch* malloc_dispatch, bool* malloc_zygote_child,
Christopher Ferris4da25032018-03-07 13:38:48 -0800175 const char* options);
Christopher Ferris63860cb2015-11-16 17:30:32 -0800176void debug_finalize();
Christopher Ferris2e1a40a2018-06-13 10:46:34 -0700177void debug_dump_heap(const char* file_name);
Christopher Ferris4da25032018-03-07 13:38:48 -0800178void debug_get_malloc_leak_info(uint8_t** info, size_t* overall_size, size_t* info_size,
179 size_t* total_memory, size_t* backtrace_size);
Christopher Ferris2e1a40a2018-06-13 10:46:34 -0700180bool debug_write_malloc_leak_info(FILE* fp);
Colin Cross2d4721c2016-02-02 11:57:54 -0800181ssize_t debug_malloc_backtrace(void* pointer, uintptr_t* frames, size_t frame_count);
Christopher Ferris63860cb2015-11-16 17:30:32 -0800182void debug_free_malloc_leak_info(uint8_t* info);
183size_t debug_malloc_usable_size(void* pointer);
184void* debug_malloc(size_t size);
185void debug_free(void* pointer);
Christopher Ferriscae21a92018-02-05 18:14:55 -0800186void* debug_aligned_alloc(size_t alignment, size_t size);
Christopher Ferris63860cb2015-11-16 17:30:32 -0800187void* debug_memalign(size_t alignment, size_t bytes);
188void* debug_realloc(void* pointer, size_t bytes);
189void* debug_calloc(size_t nmemb, size_t bytes);
190struct mallinfo debug_mallinfo();
Christopher Ferrisa1c0d2f2017-05-15 15:50:19 -0700191int debug_mallopt(int param, int value);
Christopher Ferris6c619a02019-03-01 17:59:51 -0800192int debug_malloc_info(int options, FILE* fp);
Christopher Ferris63860cb2015-11-16 17:30:32 -0800193int debug_posix_memalign(void** memptr, size_t alignment, size_t size);
Christopher Ferris6f517cd2019-11-08 11:28:38 -0800194int debug_malloc_iterate(uintptr_t base, size_t size,
195 void (*callback)(uintptr_t base, size_t size, void* arg), void* arg);
Colin Cross869691c2016-01-29 12:48:18 -0800196void debug_malloc_disable();
197void debug_malloc_enable();
Christopher Ferris63860cb2015-11-16 17:30:32 -0800198
199#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
200void* debug_pvalloc(size_t bytes);
201void* debug_valloc(size_t size);
202#endif
203
204__END_DECLS
205// ------------------------------------------------------------------------
206
Christopher Ferrisd269fcc2019-05-06 19:03:59 -0700207class ScopedConcurrentLock {
208 public:
209 ScopedConcurrentLock() {
210 pthread_rwlock_rdlock(&lock_);
211 }
212 ~ScopedConcurrentLock() {
213 pthread_rwlock_unlock(&lock_);
214 }
215
216 static void Init() {
217 pthread_rwlockattr_t attr;
218 // Set the attribute so that when a write lock is pending, read locks are no
219 // longer granted.
220 pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP);
221 pthread_rwlock_init(&lock_, &attr);
222 }
223
224 static void BlockAllOperations() {
225 pthread_rwlock_wrlock(&lock_);
226 }
227
228 private:
229 static pthread_rwlock_t lock_;
230};
231pthread_rwlock_t ScopedConcurrentLock::lock_;
232
Christopher Ferris9bf78172020-05-20 15:37:30 -0700233// Use this because the sigprocmask* functions filter out the reserved bionic
234// signals including the signal this code blocks.
235static inline int __rt_sigprocmask(int how, const sigset64_t* new_set, sigset64_t* old_set,
236 size_t sigset_size) {
237 return syscall(SYS_rt_sigprocmask, how, new_set, old_set, sigset_size);
238}
239
240// Need to block the backtrace signal while in malloc debug routines
241// otherwise there is a chance of a deadlock and timeout when unwinding.
242// This can occur if a thread is paused while owning a malloc debug
243// internal lock.
244class ScopedBacktraceSignalBlocker {
245 public:
246 ScopedBacktraceSignalBlocker() {
247 sigemptyset64(&backtrace_set_);
248 sigaddset64(&backtrace_set_, BIONIC_SIGNAL_BACKTRACE);
249 sigset64_t old_set;
250 __rt_sigprocmask(SIG_BLOCK, &backtrace_set_, &old_set, sizeof(backtrace_set_));
251 if (sigismember64(&old_set, BIONIC_SIGNAL_BACKTRACE)) {
252 unblock_ = false;
253 }
254 }
255
256 ~ScopedBacktraceSignalBlocker() {
257 if (unblock_) {
258 __rt_sigprocmask(SIG_UNBLOCK, &backtrace_set_, nullptr, sizeof(backtrace_set_));
259 }
260 }
261
262 private:
263 bool unblock_ = true;
264 sigset64_t backtrace_set_;
265};
266
Colin Cross7a28a3c2016-02-07 22:51:15 -0800267static void InitAtfork() {
268 static pthread_once_t atfork_init = PTHREAD_ONCE_INIT;
Christopher Ferris4da25032018-03-07 13:38:48 -0800269 pthread_once(&atfork_init, []() {
Colin Cross7a28a3c2016-02-07 22:51:15 -0800270 pthread_atfork(
Christopher Ferris4da25032018-03-07 13:38:48 -0800271 []() {
Colin Cross7a28a3c2016-02-07 22:51:15 -0800272 if (g_debug != nullptr) {
273 g_debug->PrepareFork();
274 }
275 },
Christopher Ferris4da25032018-03-07 13:38:48 -0800276 []() {
Colin Cross7a28a3c2016-02-07 22:51:15 -0800277 if (g_debug != nullptr) {
278 g_debug->PostForkParent();
279 }
280 },
Christopher Ferris4da25032018-03-07 13:38:48 -0800281 []() {
Colin Cross7a28a3c2016-02-07 22:51:15 -0800282 if (g_debug != nullptr) {
283 g_debug->PostForkChild();
284 }
Christopher Ferris4da25032018-03-07 13:38:48 -0800285 });
Colin Cross7a28a3c2016-02-07 22:51:15 -0800286 });
287}
Christopher Ferrisd0919622016-03-15 22:39:39 -0700288
Christopher Ferris93bdd6a2018-04-05 11:12:38 -0700289void BacktraceAndLog() {
290 if (g_debug->config().options() & BACKTRACE_FULL) {
291 std::vector<uintptr_t> frames;
Christopher Ferris459eecb2022-01-07 13:38:10 -0800292 std::vector<unwindstack::FrameData> frames_info;
Christopher Ferris93bdd6a2018-04-05 11:12:38 -0700293 if (!Unwind(&frames, &frames_info, 256)) {
294 error_log(" Backtrace failed to get any frames.");
295 } else {
296 UnwindLog(frames_info);
297 }
298 } else {
299 std::vector<uintptr_t> frames(256);
300 size_t num_frames = backtrace_get(frames.data(), frames.size());
301 if (num_frames == 0) {
302 error_log(" Backtrace failed to get any frames.");
303 } else {
304 backtrace_log(frames.data(), num_frames);
305 }
306 }
307}
308
Christopher Ferris4da25032018-03-07 13:38:48 -0800309static void LogError(const void* pointer, const char* error_str) {
Christopher Ferris63860cb2015-11-16 17:30:32 -0800310 error_log(LOG_DIVIDER);
Christopher Ferris4da25032018-03-07 13:38:48 -0800311 error_log("+++ ALLOCATION %p %s", pointer, error_str);
312
313 // If we are tracking already freed pointers, check to see if this is
314 // one so we can print extra information.
315 if (g_debug->config().options() & FREE_TRACK) {
316 PointerData::LogFreeBacktrace(pointer);
Christopher Ferris7993b802016-01-28 18:35:05 -0800317 }
Christopher Ferris4da25032018-03-07 13:38:48 -0800318
Christopher Ferris93bdd6a2018-04-05 11:12:38 -0700319 error_log("Backtrace at time of failure:");
320 BacktraceAndLog();
Christopher Ferris63860cb2015-11-16 17:30:32 -0800321 error_log(LOG_DIVIDER);
Iris Chang7f209a92019-01-16 11:17:15 +0800322 if (g_debug->config().options() & ABORT_ON_ERROR) {
323 abort();
324 }
Christopher Ferris63860cb2015-11-16 17:30:32 -0800325}
326
Christopher Ferris4da25032018-03-07 13:38:48 -0800327static bool VerifyPointer(const void* pointer, const char* function_name) {
328 if (g_debug->HeaderEnabled()) {
329 Header* header = g_debug->GetHeader(pointer);
330 if (header->tag != DEBUG_TAG) {
331 std::string error_str;
332 if (header->tag == DEBUG_FREE_TAG) {
333 error_str = std::string("USED AFTER FREE (") + function_name + ")";
334 } else {
335 error_str = android::base::StringPrintf("HAS INVALID TAG %" PRIx32 " (%s)", header->tag,
336 function_name);
337 }
338 LogError(pointer, error_str.c_str());
339 return false;
340 }
341 }
342
343 if (g_debug->TrackPointers()) {
344 if (!PointerData::Exists(pointer)) {
345 std::string error_str(std::string("UNKNOWN POINTER (") + function_name + ")");
346 LogError(pointer, error_str.c_str());
347 return false;
348 }
349 }
350 return true;
351}
352
353static size_t InternalMallocUsableSize(void* pointer) {
354 if (g_debug->HeaderEnabled()) {
355 return g_debug->GetHeader(pointer)->usable_size;
356 } else {
357 return g_dispatch->malloc_usable_size(pointer);
358 }
359}
360
Christopher Ferris63860cb2015-11-16 17:30:32 -0800361static void* InitHeader(Header* header, void* orig_pointer, size_t size) {
362 header->tag = DEBUG_TAG;
363 header->orig_pointer = orig_pointer;
364 header->size = size;
Christopher Ferris63860cb2015-11-16 17:30:32 -0800365 header->usable_size = g_dispatch->malloc_usable_size(orig_pointer);
366 if (header->usable_size == 0) {
367 g_dispatch->free(orig_pointer);
368 return nullptr;
369 }
Christopher Ferris4da25032018-03-07 13:38:48 -0800370 header->usable_size -= g_debug->pointer_offset() + reinterpret_cast<uintptr_t>(header) -
371 reinterpret_cast<uintptr_t>(orig_pointer);
Christopher Ferris63860cb2015-11-16 17:30:32 -0800372
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700373 if (g_debug->config().options() & FRONT_GUARD) {
Christopher Ferris63860cb2015-11-16 17:30:32 -0800374 uint8_t* guard = g_debug->GetFrontGuard(header);
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700375 memset(guard, g_debug->config().front_guard_value(), g_debug->config().front_guard_bytes());
Christopher Ferris63860cb2015-11-16 17:30:32 -0800376 }
377
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700378 if (g_debug->config().options() & REAR_GUARD) {
Christopher Ferris63860cb2015-11-16 17:30:32 -0800379 uint8_t* guard = g_debug->GetRearGuard(header);
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700380 memset(guard, g_debug->config().rear_guard_value(), g_debug->config().rear_guard_bytes());
Christopher Ferris63860cb2015-11-16 17:30:32 -0800381 // If the rear guard is enabled, set the usable size to the exact size
382 // of the allocation.
Christopher Ferris4da25032018-03-07 13:38:48 -0800383 header->usable_size = header->size;
Christopher Ferris63860cb2015-11-16 17:30:32 -0800384 }
385
386 return g_debug->GetPointer(header);
387}
388
Christopher Ferris705de3c2019-05-22 13:39:57 -0700389extern "C" void __asan_init() __attribute__((weak));
390
Christopher Ferris8189e772019-04-09 16:37:23 -0700391bool debug_initialize(const MallocDispatch* malloc_dispatch, bool* zygote_child,
Christopher Ferris4da25032018-03-07 13:38:48 -0800392 const char* options) {
Christopher Ferris8189e772019-04-09 16:37:23 -0700393 if (zygote_child == nullptr || options == nullptr) {
Christopher Ferris63860cb2015-11-16 17:30:32 -0800394 return false;
395 }
Colin Cross7a28a3c2016-02-07 22:51:15 -0800396
Christopher Ferris705de3c2019-05-22 13:39:57 -0700397 if (__asan_init != 0) {
398 error_log("malloc debug cannot be enabled alongside ASAN");
399 return false;
400 }
401
Colin Cross7a28a3c2016-02-07 22:51:15 -0800402 InitAtfork();
403
Christopher Ferris8189e772019-04-09 16:37:23 -0700404 g_zygote_child = zygote_child;
Christopher Ferris63860cb2015-11-16 17:30:32 -0800405
406 g_dispatch = malloc_dispatch;
407
408 if (!DebugDisableInitialize()) {
409 return false;
410 }
411
412 DebugData* debug = new DebugData();
Christopher Ferrisb42e8b42022-05-09 14:00:47 -0700413 if (!debug->Initialize(options) || !Unreachable::Initialize(debug->config())) {
Christopher Ferris63860cb2015-11-16 17:30:32 -0800414 delete debug;
415 DebugDisableFinalize();
416 return false;
417 }
418 g_debug = debug;
419
420 // Always enable the backtrace code since we will use it in a number
421 // of different error cases.
422 backtrace_startup();
423
Christopher Ferrisc328e442019-04-01 19:31:26 -0700424 if (g_debug->config().options() & VERBOSE) {
425 info_log("%s: malloc debug enabled", getprogname());
426 }
427
Christopher Ferrisd269fcc2019-05-06 19:03:59 -0700428 ScopedConcurrentLock::Init();
429
Christopher Ferris63860cb2015-11-16 17:30:32 -0800430 return true;
431}
432
433void debug_finalize() {
434 if (g_debug == nullptr) {
435 return;
436 }
437
Christopher Ferrisd269fcc2019-05-06 19:03:59 -0700438 // Make sure that there are no other threads doing debug allocations
439 // before we kill everything.
440 ScopedConcurrentLock::BlockAllOperations();
441
Christopher Ferris97b47472018-07-10 14:45:24 -0700442 // Turn off capturing allocations calls.
443 DebugDisableSet(true);
444
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700445 if (g_debug->config().options() & FREE_TRACK) {
Christopher Ferris4da25032018-03-07 13:38:48 -0800446 PointerData::VerifyAllFreed();
Christopher Ferris63860cb2015-11-16 17:30:32 -0800447 }
448
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700449 if (g_debug->config().options() & LEAK_TRACK) {
Christopher Ferris4da25032018-03-07 13:38:48 -0800450 PointerData::LogLeaks();
Christopher Ferris63860cb2015-11-16 17:30:32 -0800451 }
452
Christopher Ferris602b88c2017-08-04 13:04:04 -0700453 if ((g_debug->config().options() & BACKTRACE) && g_debug->config().backtrace_dump_on_exit()) {
Christopher Ferris4da25032018-03-07 13:38:48 -0800454 debug_dump_heap(android::base::StringPrintf("%s.%d.exit.txt",
455 g_debug->config().backtrace_dump_prefix().c_str(),
Christopher Ferris97b47472018-07-10 14:45:24 -0700456 getpid()).c_str());
Christopher Ferris602b88c2017-08-04 13:04:04 -0700457 }
458
Colin Cross2c759912016-02-05 16:17:39 -0800459 backtrace_shutdown();
460
Christopher Ferris33d73372021-07-02 15:46:18 -0700461 // In order to prevent any issues of threads freeing previous pointers
462 // after the main thread calls this code, simply leak the g_debug pointer
463 // and do not destroy the debug disable pthread key.
Christopher Ferris63860cb2015-11-16 17:30:32 -0800464}
465
Christopher Ferris4da25032018-03-07 13:38:48 -0800466void debug_get_malloc_leak_info(uint8_t** info, size_t* overall_size, size_t* info_size,
467 size_t* total_memory, size_t* backtrace_size) {
Christopher Ferrisd269fcc2019-05-06 19:03:59 -0700468 ScopedConcurrentLock lock;
Christopher Ferris63860cb2015-11-16 17:30:32 -0800469 ScopedDisableDebugCalls disable;
Christopher Ferris9bf78172020-05-20 15:37:30 -0700470 ScopedBacktraceSignalBlocker blocked;
Christopher Ferris63860cb2015-11-16 17:30:32 -0800471
472 // Verify the arguments.
Yi Kong32bc0fc2018-08-02 17:31:13 -0700473 if (info == nullptr || overall_size == nullptr || info_size == nullptr || total_memory == nullptr ||
Christopher Ferris4da25032018-03-07 13:38:48 -0800474 backtrace_size == nullptr) {
Christopher Ferris63860cb2015-11-16 17:30:32 -0800475 error_log("get_malloc_leak_info: At least one invalid parameter.");
476 return;
477 }
478
479 *info = nullptr;
480 *overall_size = 0;
481 *info_size = 0;
482 *total_memory = 0;
483 *backtrace_size = 0;
484
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700485 if (!(g_debug->config().options() & BACKTRACE)) {
Christopher Ferris4da25032018-03-07 13:38:48 -0800486 error_log(
487 "get_malloc_leak_info: Allocations not being tracked, to enable "
488 "set the option 'backtrace'.");
Christopher Ferris63860cb2015-11-16 17:30:32 -0800489 return;
490 }
491
Christopher Ferris4da25032018-03-07 13:38:48 -0800492 PointerData::GetInfo(info, overall_size, info_size, total_memory, backtrace_size);
Christopher Ferris63860cb2015-11-16 17:30:32 -0800493}
494
495void debug_free_malloc_leak_info(uint8_t* info) {
496 g_dispatch->free(info);
497}
498
Christopher Ferris55a89a42016-04-07 17:14:53 -0700499size_t debug_malloc_usable_size(void* pointer) {
Christopher Ferrisb42e8b42022-05-09 14:00:47 -0700500 Unreachable::CheckIfRequested(g_debug->config());
501
Christopher Ferris55a89a42016-04-07 17:14:53 -0700502 if (DebugCallsDisabled() || pointer == nullptr) {
503 return g_dispatch->malloc_usable_size(pointer);
Christopher Ferris63860cb2015-11-16 17:30:32 -0800504 }
Christopher Ferrisd269fcc2019-05-06 19:03:59 -0700505 ScopedConcurrentLock lock;
Christopher Ferris55a89a42016-04-07 17:14:53 -0700506 ScopedDisableDebugCalls disable;
Christopher Ferris9bf78172020-05-20 15:37:30 -0700507 ScopedBacktraceSignalBlocker blocked;
Christopher Ferris63860cb2015-11-16 17:30:32 -0800508
Christopher Ferris4da25032018-03-07 13:38:48 -0800509 if (!VerifyPointer(pointer, "malloc_usable_size")) {
510 return 0;
511 }
512
513 return InternalMallocUsableSize(pointer);
Christopher Ferris55a89a42016-04-07 17:14:53 -0700514}
515
Chia-hung Duanf7e8b172022-11-01 21:37:56 +0000516static TimedResult InternalMalloc(size_t size) {
Christopher Ferris4da25032018-03-07 13:38:48 -0800517 if ((g_debug->config().options() & BACKTRACE) && g_debug->pointer->ShouldDumpAndReset()) {
518 debug_dump_heap(android::base::StringPrintf(
519 "%s.%d.txt", g_debug->config().backtrace_dump_prefix().c_str(), getpid())
520 .c_str());
Christopher Ferris602b88c2017-08-04 13:04:04 -0700521 }
522
Colin Cross9567c7b2016-03-09 17:56:14 -0800523 if (size == 0) {
524 size = 1;
525 }
526
Chia-hung Duanf7e8b172022-11-01 21:37:56 +0000527 TimedResult result;
528
Christopher Ferris63860cb2015-11-16 17:30:32 -0800529 size_t real_size = size + g_debug->extra_bytes();
530 if (real_size < size) {
531 // Overflow.
532 errno = ENOMEM;
Chia-hung Duanf7e8b172022-11-01 21:37:56 +0000533 result.setValue<void*>(nullptr);
534 return result;
Christopher Ferris63860cb2015-11-16 17:30:32 -0800535 }
536
Christopher Ferris4da25032018-03-07 13:38:48 -0800537 if (size > PointerInfoType::MaxSize()) {
538 errno = ENOMEM;
Chia-hung Duanf7e8b172022-11-01 21:37:56 +0000539 result.setValue<void*>(nullptr);
540 return result;
Christopher Ferris4da25032018-03-07 13:38:48 -0800541 }
Christopher Ferris63860cb2015-11-16 17:30:32 -0800542
Christopher Ferris4da25032018-03-07 13:38:48 -0800543 if (g_debug->HeaderEnabled()) {
Chia-hung Duanf7e8b172022-11-01 21:37:56 +0000544 result = TCALL(memalign, MINIMUM_ALIGNMENT_BYTES, real_size);
545 Header* header = reinterpret_cast<Header*>(result.getValue<void*>());
Christopher Ferris63860cb2015-11-16 17:30:32 -0800546 if (header == nullptr) {
Chia-hung Duanf7e8b172022-11-01 21:37:56 +0000547 return result;
Christopher Ferris63860cb2015-11-16 17:30:32 -0800548 }
Chia-hung Duanf7e8b172022-11-01 21:37:56 +0000549 result.setValue<void*>(InitHeader(header, header, size));
Christopher Ferris63860cb2015-11-16 17:30:32 -0800550 } else {
Chia-hung Duanf7e8b172022-11-01 21:37:56 +0000551 result = TCALL(malloc, real_size);
Christopher Ferris63860cb2015-11-16 17:30:32 -0800552 }
553
Chia-hung Duanf7e8b172022-11-01 21:37:56 +0000554 void* pointer = result.getValue<void*>();
555
Christopher Ferris4da25032018-03-07 13:38:48 -0800556 if (pointer != nullptr) {
557 if (g_debug->TrackPointers()) {
558 PointerData::Add(pointer, size);
559 }
560
561 if (g_debug->config().options() & FILL_ON_ALLOC) {
562 size_t bytes = InternalMallocUsableSize(pointer);
563 size_t fill_bytes = g_debug->config().fill_on_alloc_bytes();
564 bytes = (bytes < fill_bytes) ? bytes : fill_bytes;
565 memset(pointer, g_debug->config().fill_alloc_value(), bytes);
566 }
Christopher Ferris63860cb2015-11-16 17:30:32 -0800567 }
Chia-hung Duanf7e8b172022-11-01 21:37:56 +0000568
569 return result;
Christopher Ferris63860cb2015-11-16 17:30:32 -0800570}
571
Christopher Ferris55a89a42016-04-07 17:14:53 -0700572void* debug_malloc(size_t size) {
Christopher Ferrisb42e8b42022-05-09 14:00:47 -0700573 Unreachable::CheckIfRequested(g_debug->config());
574
Christopher Ferris55a89a42016-04-07 17:14:53 -0700575 if (DebugCallsDisabled()) {
576 return g_dispatch->malloc(size);
Christopher Ferris63860cb2015-11-16 17:30:32 -0800577 }
Christopher Ferrisd269fcc2019-05-06 19:03:59 -0700578 ScopedConcurrentLock lock;
Christopher Ferris55a89a42016-04-07 17:14:53 -0700579 ScopedDisableDebugCalls disable;
Christopher Ferris9bf78172020-05-20 15:37:30 -0700580 ScopedBacktraceSignalBlocker blocked;
Christopher Ferris63860cb2015-11-16 17:30:32 -0800581
Chia-hung Duanf7e8b172022-11-01 21:37:56 +0000582 TimedResult result = InternalMalloc(size);
Christopher Ferris7bd01782016-04-20 12:30:58 -0700583
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700584 if (g_debug->config().options() & RECORD_ALLOCS) {
Chia-hung Duanf7e8b172022-11-01 21:37:56 +0000585 g_debug->record->AddEntry(new MallocEntry(result.getValue<void*>(), size,
586 result.GetStartTimeNS(), result.GetEndTimeNS()));
Christopher Ferris7bd01782016-04-20 12:30:58 -0700587 }
588
Chia-hung Duanf7e8b172022-11-01 21:37:56 +0000589 return result.getValue<void*>();
Christopher Ferris55a89a42016-04-07 17:14:53 -0700590}
591
Chia-hung Duanf7e8b172022-11-01 21:37:56 +0000592static TimedResult InternalFree(void* pointer) {
Christopher Ferris4da25032018-03-07 13:38:48 -0800593 if ((g_debug->config().options() & BACKTRACE) && g_debug->pointer->ShouldDumpAndReset()) {
594 debug_dump_heap(android::base::StringPrintf(
595 "%s.%d.txt", g_debug->config().backtrace_dump_prefix().c_str(), getpid())
596 .c_str());
Christopher Ferris602b88c2017-08-04 13:04:04 -0700597 }
598
Christopher Ferris63860cb2015-11-16 17:30:32 -0800599 void* free_pointer = pointer;
600 size_t bytes;
Christopher Ferrisd0919622016-03-15 22:39:39 -0700601 Header* header;
Christopher Ferris4da25032018-03-07 13:38:48 -0800602 if (g_debug->HeaderEnabled()) {
Christopher Ferrisd0919622016-03-15 22:39:39 -0700603 header = g_debug->GetHeader(pointer);
Christopher Ferris63860cb2015-11-16 17:30:32 -0800604 free_pointer = header->orig_pointer;
605
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700606 if (g_debug->config().options() & FRONT_GUARD) {
Christopher Ferris55a89a42016-04-07 17:14:53 -0700607 if (!g_debug->front_guard->Valid(header)) {
608 g_debug->front_guard->LogFailure(header);
Christopher Ferris63860cb2015-11-16 17:30:32 -0800609 }
610 }
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700611 if (g_debug->config().options() & REAR_GUARD) {
Christopher Ferris55a89a42016-04-07 17:14:53 -0700612 if (!g_debug->rear_guard->Valid(header)) {
613 g_debug->rear_guard->LogFailure(header);
Christopher Ferris63860cb2015-11-16 17:30:32 -0800614 }
615 }
616
Christopher Ferris7993b802016-01-28 18:35:05 -0800617 header->tag = DEBUG_FREE_TAG;
Christopher Ferris63860cb2015-11-16 17:30:32 -0800618
619 bytes = header->usable_size;
620 } else {
621 bytes = g_dispatch->malloc_usable_size(pointer);
622 }
623
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700624 if (g_debug->config().options() & FILL_ON_FREE) {
625 size_t fill_bytes = g_debug->config().fill_on_free_bytes();
Christopher Ferrisa3836482022-05-13 12:09:39 -0700626 fill_bytes = (bytes < fill_bytes) ? bytes : fill_bytes;
627 memset(pointer, g_debug->config().fill_free_value(), fill_bytes);
Christopher Ferris63860cb2015-11-16 17:30:32 -0800628 }
629
Christopher Ferris4da25032018-03-07 13:38:48 -0800630 if (g_debug->TrackPointers()) {
631 PointerData::Remove(pointer);
632 }
633
Chia-hung Duanf7e8b172022-11-01 21:37:56 +0000634 TimedResult result;
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700635 if (g_debug->config().options() & FREE_TRACK) {
Christopher Ferrisd0919622016-03-15 22:39:39 -0700636 // Do not add the allocation until we are done modifying the pointer
637 // itself. This avoids a race if a lot of threads are all doing
638 // frees at the same time and we wind up trying to really free this
639 // pointer from another thread, while still trying to free it in
640 // this function.
Christopher Ferrisa3836482022-05-13 12:09:39 -0700641 pointer = PointerData::AddFreed(pointer, bytes);
Chia-hung Duanf7e8b172022-11-01 21:37:56 +0000642 if (pointer != nullptr && g_debug->HeaderEnabled()) {
643 pointer = g_debug->GetHeader(pointer)->orig_pointer;
Christopher Ferris4da25032018-03-07 13:38:48 -0800644 }
Chia-hung Duanf7e8b172022-11-01 21:37:56 +0000645 result = TCALLVOID(free, pointer);
Christopher Ferrisd0919622016-03-15 22:39:39 -0700646 } else {
Chia-hung Duanf7e8b172022-11-01 21:37:56 +0000647 result = TCALLVOID(free, free_pointer);
Christopher Ferrisd0919622016-03-15 22:39:39 -0700648 }
Chia-hung Duanf7e8b172022-11-01 21:37:56 +0000649
650 return result;
Christopher Ferris63860cb2015-11-16 17:30:32 -0800651}
652
Christopher Ferris55a89a42016-04-07 17:14:53 -0700653void debug_free(void* pointer) {
Christopher Ferrisb42e8b42022-05-09 14:00:47 -0700654 Unreachable::CheckIfRequested(g_debug->config());
655
Christopher Ferris55a89a42016-04-07 17:14:53 -0700656 if (DebugCallsDisabled() || pointer == nullptr) {
657 return g_dispatch->free(pointer);
658 }
Christopher Ferrisd269fcc2019-05-06 19:03:59 -0700659 ScopedConcurrentLock lock;
Christopher Ferris55a89a42016-04-07 17:14:53 -0700660 ScopedDisableDebugCalls disable;
Christopher Ferris9bf78172020-05-20 15:37:30 -0700661 ScopedBacktraceSignalBlocker blocked;
Christopher Ferris55a89a42016-04-07 17:14:53 -0700662
Christopher Ferris4da25032018-03-07 13:38:48 -0800663 if (!VerifyPointer(pointer, "free")) {
664 return;
665 }
666
Chia-hung Duanf7e8b172022-11-01 21:37:56 +0000667 TimedResult result = InternalFree(pointer);
668
669 if (g_debug->config().options() & RECORD_ALLOCS) {
670 g_debug->record->AddEntry(
671 new FreeEntry(pointer, result.GetStartTimeNS(), result.GetEndTimeNS()));
672 }
Christopher Ferris55a89a42016-04-07 17:14:53 -0700673}
674
Christopher Ferris63860cb2015-11-16 17:30:32 -0800675void* debug_memalign(size_t alignment, size_t bytes) {
Christopher Ferrisb42e8b42022-05-09 14:00:47 -0700676 Unreachable::CheckIfRequested(g_debug->config());
677
Christopher Ferris63860cb2015-11-16 17:30:32 -0800678 if (DebugCallsDisabled()) {
679 return g_dispatch->memalign(alignment, bytes);
680 }
Christopher Ferrisd269fcc2019-05-06 19:03:59 -0700681 ScopedConcurrentLock lock;
Christopher Ferris55a89a42016-04-07 17:14:53 -0700682 ScopedDisableDebugCalls disable;
Christopher Ferris9bf78172020-05-20 15:37:30 -0700683 ScopedBacktraceSignalBlocker blocked;
Christopher Ferris63860cb2015-11-16 17:30:32 -0800684
Colin Cross9567c7b2016-03-09 17:56:14 -0800685 if (bytes == 0) {
686 bytes = 1;
687 }
688
Christopher Ferris4da25032018-03-07 13:38:48 -0800689 if (bytes > PointerInfoType::MaxSize()) {
690 errno = ENOMEM;
691 return nullptr;
692 }
Christopher Ferris63860cb2015-11-16 17:30:32 -0800693
Chia-hung Duanf7e8b172022-11-01 21:37:56 +0000694 TimedResult result;
Christopher Ferris4da25032018-03-07 13:38:48 -0800695 void* pointer;
696 if (g_debug->HeaderEnabled()) {
Christopher Ferris63860cb2015-11-16 17:30:32 -0800697 // Make the alignment a power of two.
698 if (!powerof2(alignment)) {
699 alignment = BIONIC_ROUND_UP_POWER_OF_2(alignment);
700 }
Christopher Ferris72df6702016-02-11 15:51:31 -0800701 // Force the alignment to at least MINIMUM_ALIGNMENT_BYTES to guarantee
Christopher Ferris63860cb2015-11-16 17:30:32 -0800702 // that the header is aligned properly.
Christopher Ferris72df6702016-02-11 15:51:31 -0800703 if (alignment < MINIMUM_ALIGNMENT_BYTES) {
704 alignment = MINIMUM_ALIGNMENT_BYTES;
Christopher Ferris63860cb2015-11-16 17:30:32 -0800705 }
706
707 // We don't have any idea what the natural alignment of
708 // the underlying native allocator is, so we always need to
709 // over allocate.
710 size_t real_size = alignment + bytes + g_debug->extra_bytes();
711 if (real_size < bytes) {
712 // Overflow.
713 errno = ENOMEM;
714 return nullptr;
715 }
716
Chia-hung Duanf7e8b172022-11-01 21:37:56 +0000717 result = TCALL(malloc, real_size);
718 pointer = result.getValue<void*>();
Christopher Ferris63860cb2015-11-16 17:30:32 -0800719 if (pointer == nullptr) {
720 return nullptr;
721 }
722
723 uintptr_t value = reinterpret_cast<uintptr_t>(pointer) + g_debug->pointer_offset();
724 // Now align the pointer.
725 value += (-value % alignment);
726
727 Header* header = g_debug->GetHeader(reinterpret_cast<void*>(value));
Chia-hung Duanf7e8b172022-11-01 21:37:56 +0000728 // Don't need to update `result` here because we only need the timestamps.
Christopher Ferris63860cb2015-11-16 17:30:32 -0800729 pointer = InitHeader(header, pointer, bytes);
730 } else {
731 size_t real_size = bytes + g_debug->extra_bytes();
732 if (real_size < bytes) {
733 // Overflow.
734 errno = ENOMEM;
735 return nullptr;
736 }
Chia-hung Duanf7e8b172022-11-01 21:37:56 +0000737 result = TCALL(memalign, alignment, real_size);
738 pointer = result.getValue<void*>();
Christopher Ferris63860cb2015-11-16 17:30:32 -0800739 }
740
Christopher Ferris4da25032018-03-07 13:38:48 -0800741 if (pointer != nullptr) {
742 if (g_debug->TrackPointers()) {
743 PointerData::Add(pointer, bytes);
744 }
Christopher Ferris55a89a42016-04-07 17:14:53 -0700745
Christopher Ferris4da25032018-03-07 13:38:48 -0800746 if (g_debug->config().options() & FILL_ON_ALLOC) {
747 size_t bytes = InternalMallocUsableSize(pointer);
748 size_t fill_bytes = g_debug->config().fill_on_alloc_bytes();
749 bytes = (bytes < fill_bytes) ? bytes : fill_bytes;
750 memset(pointer, g_debug->config().fill_alloc_value(), bytes);
751 }
752
753 if (g_debug->config().options() & RECORD_ALLOCS) {
Chia-hung Duanf7e8b172022-11-01 21:37:56 +0000754 g_debug->record->AddEntry(new MemalignEntry(pointer, bytes, alignment,
755 result.GetStartTimeNS(), result.GetEndTimeNS()));
Christopher Ferris4da25032018-03-07 13:38:48 -0800756 }
Christopher Ferris7bd01782016-04-20 12:30:58 -0700757 }
758
Christopher Ferris63860cb2015-11-16 17:30:32 -0800759 return pointer;
760}
761
762void* debug_realloc(void* pointer, size_t bytes) {
Christopher Ferrisb42e8b42022-05-09 14:00:47 -0700763 Unreachable::CheckIfRequested(g_debug->config());
764
Christopher Ferris63860cb2015-11-16 17:30:32 -0800765 if (DebugCallsDisabled()) {
766 return g_dispatch->realloc(pointer, bytes);
767 }
Christopher Ferrisd269fcc2019-05-06 19:03:59 -0700768 ScopedConcurrentLock lock;
Christopher Ferris55a89a42016-04-07 17:14:53 -0700769 ScopedDisableDebugCalls disable;
Christopher Ferris9bf78172020-05-20 15:37:30 -0700770 ScopedBacktraceSignalBlocker blocked;
Christopher Ferris63860cb2015-11-16 17:30:32 -0800771
772 if (pointer == nullptr) {
Chia-hung Duanf7e8b172022-11-01 21:37:56 +0000773 TimedResult result = InternalMalloc(bytes);
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700774 if (g_debug->config().options() & RECORD_ALLOCS) {
Chia-hung Duanf7e8b172022-11-01 21:37:56 +0000775 g_debug->record->AddEntry(new ReallocEntry(result.getValue<void*>(), bytes, nullptr,
776 result.GetStartTimeNS(), result.GetEndTimeNS()));
Christopher Ferris7bd01782016-04-20 12:30:58 -0700777 }
Chia-hung Duanf7e8b172022-11-01 21:37:56 +0000778 pointer = result.getValue<void*>();
Christopher Ferris7bd01782016-04-20 12:30:58 -0700779 return pointer;
Christopher Ferris63860cb2015-11-16 17:30:32 -0800780 }
781
Christopher Ferris4da25032018-03-07 13:38:48 -0800782 if (!VerifyPointer(pointer, "realloc")) {
783 return nullptr;
784 }
785
Christopher Ferris63860cb2015-11-16 17:30:32 -0800786 if (bytes == 0) {
Chia-hung Duanf7e8b172022-11-01 21:37:56 +0000787 TimedResult result = InternalFree(pointer);
788
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700789 if (g_debug->config().options() & RECORD_ALLOCS) {
Chia-hung Duanf7e8b172022-11-01 21:37:56 +0000790 g_debug->record->AddEntry(new ReallocEntry(nullptr, bytes, pointer, result.GetStartTimeNS(),
791 result.GetEndTimeNS()));
Christopher Ferris7bd01782016-04-20 12:30:58 -0700792 }
793
Christopher Ferris63860cb2015-11-16 17:30:32 -0800794 return nullptr;
795 }
796
797 size_t real_size = bytes;
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700798 if (g_debug->config().options() & EXPAND_ALLOC) {
799 real_size += g_debug->config().expand_alloc_bytes();
Christopher Ferris63860cb2015-11-16 17:30:32 -0800800 if (real_size < bytes) {
801 // Overflow.
802 errno = ENOMEM;
803 return nullptr;
804 }
805 }
806
Christopher Ferris4da25032018-03-07 13:38:48 -0800807 if (bytes > PointerInfoType::MaxSize()) {
808 errno = ENOMEM;
809 return nullptr;
810 }
811
Chia-hung Duanf7e8b172022-11-01 21:37:56 +0000812 TimedResult result;
Christopher Ferris63860cb2015-11-16 17:30:32 -0800813 void* new_pointer;
814 size_t prev_size;
Christopher Ferris4da25032018-03-07 13:38:48 -0800815 if (g_debug->HeaderEnabled()) {
Christopher Ferris63860cb2015-11-16 17:30:32 -0800816 // Same size, do nothing.
Christopher Ferris4da25032018-03-07 13:38:48 -0800817 Header* header = g_debug->GetHeader(pointer);
818 if (real_size == header->size) {
819 if (g_debug->TrackPointers()) {
820 // Remove and re-add so that the backtrace is updated.
821 PointerData::Remove(pointer);
822 PointerData::Add(pointer, real_size);
823 }
Christopher Ferris63860cb2015-11-16 17:30:32 -0800824 return pointer;
825 }
826
827 // Allocation is shrinking.
828 if (real_size < header->usable_size) {
829 header->size = real_size;
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700830 if (g_debug->config().options() & REAR_GUARD) {
Christopher Ferris63860cb2015-11-16 17:30:32 -0800831 // Don't bother allocating a smaller pointer in this case, simply
832 // change the header usable_size and reset the rear guard.
Christopher Ferris4da25032018-03-07 13:38:48 -0800833 header->usable_size = header->size;
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700834 memset(g_debug->GetRearGuard(header), g_debug->config().rear_guard_value(),
835 g_debug->config().rear_guard_bytes());
Christopher Ferris63860cb2015-11-16 17:30:32 -0800836 }
Christopher Ferris4da25032018-03-07 13:38:48 -0800837 if (g_debug->TrackPointers()) {
838 // Remove and re-add so that the backtrace is updated.
839 PointerData::Remove(pointer);
840 PointerData::Add(pointer, real_size);
841 }
Christopher Ferris63860cb2015-11-16 17:30:32 -0800842 return pointer;
843 }
844
845 // Allocate the new size.
Chia-hung Duanf7e8b172022-11-01 21:37:56 +0000846 result = InternalMalloc(bytes);
847 new_pointer = result.getValue<void*>();
Christopher Ferris63860cb2015-11-16 17:30:32 -0800848 if (new_pointer == nullptr) {
849 errno = ENOMEM;
850 return nullptr;
851 }
852
853 prev_size = header->usable_size;
854 memcpy(new_pointer, pointer, prev_size);
Chia-hung Duanf7e8b172022-11-01 21:37:56 +0000855 TimedResult free_time = InternalFree(pointer);
856 // `realloc` is split into two steps, update the end time to the finish time
857 // of the second operation.
858 result.SetEndTimeNS(free_time.GetEndTimeNS());
Christopher Ferris63860cb2015-11-16 17:30:32 -0800859 } else {
Christopher Ferris4da25032018-03-07 13:38:48 -0800860 if (g_debug->TrackPointers()) {
861 PointerData::Remove(pointer);
862 }
863
Christopher Ferris63860cb2015-11-16 17:30:32 -0800864 prev_size = g_dispatch->malloc_usable_size(pointer);
Chia-hung Duanf7e8b172022-11-01 21:37:56 +0000865 result = TCALL(realloc, pointer, real_size);
866 new_pointer = result.getValue<void*>();
Christopher Ferris63860cb2015-11-16 17:30:32 -0800867 if (new_pointer == nullptr) {
868 return nullptr;
869 }
Christopher Ferris4da25032018-03-07 13:38:48 -0800870
871 if (g_debug->TrackPointers()) {
872 PointerData::Add(new_pointer, real_size);
873 }
Christopher Ferris63860cb2015-11-16 17:30:32 -0800874 }
875
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700876 if (g_debug->config().options() & FILL_ON_ALLOC) {
Christopher Ferris4da25032018-03-07 13:38:48 -0800877 size_t bytes = InternalMallocUsableSize(new_pointer);
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700878 if (bytes > g_debug->config().fill_on_alloc_bytes()) {
879 bytes = g_debug->config().fill_on_alloc_bytes();
Christopher Ferris63860cb2015-11-16 17:30:32 -0800880 }
881 if (bytes > prev_size) {
882 memset(reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(new_pointer) + prev_size),
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700883 g_debug->config().fill_alloc_value(), bytes - prev_size);
Christopher Ferris63860cb2015-11-16 17:30:32 -0800884 }
885 }
886
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700887 if (g_debug->config().options() & RECORD_ALLOCS) {
Chia-hung Duanf7e8b172022-11-01 21:37:56 +0000888 g_debug->record->AddEntry(new ReallocEntry(new_pointer, bytes, pointer, result.GetStartTimeNS(),
889 result.GetEndTimeNS()));
Christopher Ferris7bd01782016-04-20 12:30:58 -0700890 }
891
Christopher Ferris63860cb2015-11-16 17:30:32 -0800892 return new_pointer;
893}
894
895void* debug_calloc(size_t nmemb, size_t bytes) {
Christopher Ferrisb42e8b42022-05-09 14:00:47 -0700896 Unreachable::CheckIfRequested(g_debug->config());
897
Christopher Ferris63860cb2015-11-16 17:30:32 -0800898 if (DebugCallsDisabled()) {
899 return g_dispatch->calloc(nmemb, bytes);
900 }
Christopher Ferrisd269fcc2019-05-06 19:03:59 -0700901 ScopedConcurrentLock lock;
Christopher Ferris55a89a42016-04-07 17:14:53 -0700902 ScopedDisableDebugCalls disable;
Christopher Ferris9bf78172020-05-20 15:37:30 -0700903 ScopedBacktraceSignalBlocker blocked;
Christopher Ferris63860cb2015-11-16 17:30:32 -0800904
Colin Cross7877df62016-03-10 13:01:27 -0800905 size_t size;
906 if (__builtin_mul_overflow(nmemb, bytes, &size)) {
907 // Overflow
908 errno = ENOMEM;
909 return nullptr;
910 }
911
Colin Cross9567c7b2016-03-09 17:56:14 -0800912 if (size == 0) {
913 size = 1;
914 }
915
Colin Cross7877df62016-03-10 13:01:27 -0800916 size_t real_size;
917 if (__builtin_add_overflow(size, g_debug->extra_bytes(), &real_size)) {
Christopher Ferris63860cb2015-11-16 17:30:32 -0800918 // Overflow.
919 errno = ENOMEM;
920 return nullptr;
921 }
922
Christopher Ferris4da25032018-03-07 13:38:48 -0800923 if (real_size > PointerInfoType::MaxSize()) {
924 errno = ENOMEM;
925 return nullptr;
926 }
Christopher Ferris63860cb2015-11-16 17:30:32 -0800927
Christopher Ferris4da25032018-03-07 13:38:48 -0800928 void* pointer;
Chia-hung Duanf7e8b172022-11-01 21:37:56 +0000929 TimedResult result;
Christopher Ferris4da25032018-03-07 13:38:48 -0800930 if (g_debug->HeaderEnabled()) {
Christopher Ferris63860cb2015-11-16 17:30:32 -0800931 // Need to guarantee the alignment of the header.
Chia-hung Duanf7e8b172022-11-01 21:37:56 +0000932 result = TCALL(memalign, MINIMUM_ALIGNMENT_BYTES, real_size);
933 Header* header = reinterpret_cast<Header*>(result.getValue<void*>());
Christopher Ferris63860cb2015-11-16 17:30:32 -0800934 if (header == nullptr) {
935 return nullptr;
936 }
937 memset(header, 0, g_dispatch->malloc_usable_size(header));
Christopher Ferris7bd01782016-04-20 12:30:58 -0700938 pointer = InitHeader(header, header, size);
Christopher Ferris63860cb2015-11-16 17:30:32 -0800939 } else {
Chia-hung Duanf7e8b172022-11-01 21:37:56 +0000940 result = TCALL(calloc, 1, real_size);
941 pointer = result.getValue<void*>();
Christopher Ferris63860cb2015-11-16 17:30:32 -0800942 }
Christopher Ferris4da25032018-03-07 13:38:48 -0800943
Christopher Ferris2b2b25b2017-04-05 19:13:03 -0700944 if (g_debug->config().options() & RECORD_ALLOCS) {
Chia-hung Duanf7e8b172022-11-01 21:37:56 +0000945 g_debug->record->AddEntry(
Greg Kaiser23352132023-01-09 17:53:07 +0000946 new CallocEntry(pointer, nmemb, bytes, result.GetStartTimeNS(), result.GetEndTimeNS()));
Christopher Ferris7bd01782016-04-20 12:30:58 -0700947 }
Christopher Ferris4da25032018-03-07 13:38:48 -0800948
949 if (pointer != nullptr && g_debug->TrackPointers()) {
950 PointerData::Add(pointer, size);
951 }
Christopher Ferris7bd01782016-04-20 12:30:58 -0700952 return pointer;
Christopher Ferris63860cb2015-11-16 17:30:32 -0800953}
954
955struct mallinfo debug_mallinfo() {
956 return g_dispatch->mallinfo();
957}
958
Christopher Ferrisa1c0d2f2017-05-15 15:50:19 -0700959int debug_mallopt(int param, int value) {
960 return g_dispatch->mallopt(param, value);
961}
962
Christopher Ferris6c619a02019-03-01 17:59:51 -0800963int debug_malloc_info(int options, FILE* fp) {
964 if (DebugCallsDisabled() || !g_debug->TrackPointers()) {
965 return g_dispatch->malloc_info(options, fp);
966 }
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800967
968 // Make sure any pending output is written to the file.
969 fflush(fp);
970
Christopher Ferrisd269fcc2019-05-06 19:03:59 -0700971 ScopedConcurrentLock lock;
972 ScopedDisableDebugCalls disable;
Christopher Ferris9bf78172020-05-20 15:37:30 -0700973 ScopedBacktraceSignalBlocker blocked;
Christopher Ferris6c619a02019-03-01 17:59:51 -0800974
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800975 // Avoid any issues where allocations are made that will be freed
976 // in the fclose.
977 int fd = fileno(fp);
978 MallocXmlElem root(fd, "malloc", "version=\"debug-malloc-1\"");
Christopher Ferris6c619a02019-03-01 17:59:51 -0800979 std::vector<ListInfoType> list;
980 PointerData::GetAllocList(&list);
981
982 size_t alloc_num = 0;
983 for (size_t i = 0; i < list.size(); i++) {
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800984 MallocXmlElem alloc(fd, "allocation", "nr=\"%zu\"", alloc_num);
Christopher Ferris6c619a02019-03-01 17:59:51 -0800985
986 size_t total = 1;
987 size_t size = list[i].size;
988 while (i < list.size() - 1 && list[i + 1].size == size) {
989 i++;
990 total++;
991 }
Christopher Ferrisff88fb02019-11-04 18:40:00 -0800992 MallocXmlElem(fd, "size").Contents("%zu", list[i].size);
993 MallocXmlElem(fd, "total").Contents("%zu", total);
Christopher Ferris6c619a02019-03-01 17:59:51 -0800994 alloc_num++;
995 }
996 return 0;
997}
998
Christopher Ferriscae21a92018-02-05 18:14:55 -0800999void* debug_aligned_alloc(size_t alignment, size_t size) {
Christopher Ferrisb42e8b42022-05-09 14:00:47 -07001000 Unreachable::CheckIfRequested(g_debug->config());
1001
Christopher Ferriscae21a92018-02-05 18:14:55 -08001002 if (DebugCallsDisabled()) {
1003 return g_dispatch->aligned_alloc(alignment, size);
1004 }
Christopher Ferrisa22f5d52019-03-01 16:40:59 -08001005 if (!powerof2(alignment) || (size % alignment) != 0) {
Christopher Ferriscae21a92018-02-05 18:14:55 -08001006 errno = EINVAL;
1007 return nullptr;
1008 }
1009 return debug_memalign(alignment, size);
1010}
1011
Christopher Ferris63860cb2015-11-16 17:30:32 -08001012int debug_posix_memalign(void** memptr, size_t alignment, size_t size) {
Christopher Ferrisb42e8b42022-05-09 14:00:47 -07001013 Unreachable::CheckIfRequested(g_debug->config());
1014
Christopher Ferris63860cb2015-11-16 17:30:32 -08001015 if (DebugCallsDisabled()) {
1016 return g_dispatch->posix_memalign(memptr, alignment, size);
1017 }
1018
Christopher Ferris6c619a02019-03-01 17:59:51 -08001019 if (alignment < sizeof(void*) || !powerof2(alignment)) {
Christopher Ferris63860cb2015-11-16 17:30:32 -08001020 return EINVAL;
1021 }
1022 int saved_errno = errno;
1023 *memptr = debug_memalign(alignment, size);
1024 errno = saved_errno;
1025 return (*memptr != nullptr) ? 0 : ENOMEM;
1026}
1027
Christopher Ferris6f517cd2019-11-08 11:28:38 -08001028int debug_malloc_iterate(uintptr_t base, size_t size, void (*callback)(uintptr_t, size_t, void*),
Christopher Ferris4da25032018-03-07 13:38:48 -08001029 void* arg) {
Christopher Ferrisd269fcc2019-05-06 19:03:59 -07001030 ScopedConcurrentLock lock;
Christopher Ferris4da25032018-03-07 13:38:48 -08001031 if (g_debug->TrackPointers()) {
Christopher Ferrisf78486f2022-05-04 14:08:54 -07001032 PointerData::IteratePointers([&callback, &arg](uintptr_t pointer) {
1033 callback(pointer, InternalMallocUsableSize(reinterpret_cast<void*>(pointer)), arg);
1034 });
Christopher Ferris4da25032018-03-07 13:38:48 -08001035 return 0;
1036 }
Colin Cross869691c2016-01-29 12:48:18 -08001037
Christopher Ferris4da25032018-03-07 13:38:48 -08001038 // An option that adds a header will add pointer tracking, so no need to
1039 // check if headers are enabled.
Christopher Ferris6f517cd2019-11-08 11:28:38 -08001040 return g_dispatch->malloc_iterate(base, size, callback, arg);
Colin Cross869691c2016-01-29 12:48:18 -08001041}
1042
1043void debug_malloc_disable() {
Christopher Ferrisd269fcc2019-05-06 19:03:59 -07001044 ScopedConcurrentLock lock;
Colin Cross869691c2016-01-29 12:48:18 -08001045 g_dispatch->malloc_disable();
Christopher Ferris4da25032018-03-07 13:38:48 -08001046 if (g_debug->pointer) {
1047 g_debug->pointer->PrepareFork();
Colin Cross869691c2016-01-29 12:48:18 -08001048 }
1049}
1050
1051void debug_malloc_enable() {
Christopher Ferrisd269fcc2019-05-06 19:03:59 -07001052 ScopedConcurrentLock lock;
Christopher Ferris4da25032018-03-07 13:38:48 -08001053 if (g_debug->pointer) {
1054 g_debug->pointer->PostForkParent();
Colin Cross869691c2016-01-29 12:48:18 -08001055 }
1056 g_dispatch->malloc_enable();
1057}
1058
Christopher Ferris4da25032018-03-07 13:38:48 -08001059ssize_t debug_malloc_backtrace(void* pointer, uintptr_t* frames, size_t max_frames) {
Colin Cross2d4721c2016-02-02 11:57:54 -08001060 if (DebugCallsDisabled() || pointer == nullptr) {
1061 return 0;
1062 }
Christopher Ferrisd269fcc2019-05-06 19:03:59 -07001063 ScopedConcurrentLock lock;
Christopher Ferris55a89a42016-04-07 17:14:53 -07001064 ScopedDisableDebugCalls disable;
Christopher Ferris9bf78172020-05-20 15:37:30 -07001065 ScopedBacktraceSignalBlocker blocked;
Colin Cross2d4721c2016-02-02 11:57:54 -08001066
Christopher Ferris4da25032018-03-07 13:38:48 -08001067 if (!(g_debug->config().options() & BACKTRACE)) {
1068 return 0;
Colin Cross2d4721c2016-02-02 11:57:54 -08001069 }
Mitch Phillips3b21ada2020-01-07 15:47:47 -08001070 pointer = UntagPointer(pointer);
Christopher Ferris4da25032018-03-07 13:38:48 -08001071 return PointerData::GetFrames(pointer, frames, max_frames);
Colin Cross2d4721c2016-02-02 11:57:54 -08001072}
1073
Christopher Ferris63860cb2015-11-16 17:30:32 -08001074#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
1075void* debug_pvalloc(size_t bytes) {
Christopher Ferrisb42e8b42022-05-09 14:00:47 -07001076 Unreachable::CheckIfRequested(g_debug->config());
1077
Christopher Ferris63860cb2015-11-16 17:30:32 -08001078 if (DebugCallsDisabled()) {
1079 return g_dispatch->pvalloc(bytes);
1080 }
1081
1082 size_t pagesize = getpagesize();
Dan Alberta613d0d2017-10-05 16:39:33 -07001083 size_t size = __BIONIC_ALIGN(bytes, pagesize);
Christopher Ferris63860cb2015-11-16 17:30:32 -08001084 if (size < bytes) {
1085 // Overflow
1086 errno = ENOMEM;
1087 return nullptr;
1088 }
1089 return debug_memalign(pagesize, size);
1090}
1091
1092void* debug_valloc(size_t size) {
Christopher Ferrisb42e8b42022-05-09 14:00:47 -07001093 Unreachable::CheckIfRequested(g_debug->config());
1094
Christopher Ferris63860cb2015-11-16 17:30:32 -08001095 if (DebugCallsDisabled()) {
1096 return g_dispatch->valloc(size);
1097 }
1098 return debug_memalign(getpagesize(), size);
1099}
1100#endif
Christopher Ferris602b88c2017-08-04 13:04:04 -07001101
1102static std::mutex g_dump_lock;
1103
Christopher Ferrisff88fb02019-11-04 18:40:00 -08001104static void write_dump(int fd) {
1105 dprintf(fd, "Android Native Heap Dump v1.2\n\n");
Christopher Ferris602b88c2017-08-04 13:04:04 -07001106
Christopher Ferris2e1a40a2018-06-13 10:46:34 -07001107 std::string fingerprint = android::base::GetProperty("ro.build.fingerprint", "unknown");
Christopher Ferrisff88fb02019-11-04 18:40:00 -08001108 dprintf(fd, "Build fingerprint: '%s'\n\n", fingerprint.c_str());
Christopher Ferris602b88c2017-08-04 13:04:04 -07001109
Christopher Ferrisff88fb02019-11-04 18:40:00 -08001110 PointerData::DumpLiveToFile(fd);
Christopher Ferris602b88c2017-08-04 13:04:04 -07001111
Christopher Ferrisff88fb02019-11-04 18:40:00 -08001112 dprintf(fd, "MAPS\n");
Christopher Ferris602b88c2017-08-04 13:04:04 -07001113 std::string content;
1114 if (!android::base::ReadFileToString("/proc/self/maps", &content)) {
Christopher Ferrisff88fb02019-11-04 18:40:00 -08001115 dprintf(fd, "Could not open /proc/self/maps\n");
Christopher Ferris602b88c2017-08-04 13:04:04 -07001116 } else {
Christopher Ferrisff88fb02019-11-04 18:40:00 -08001117 dprintf(fd, "%s", content.c_str());
Christopher Ferris602b88c2017-08-04 13:04:04 -07001118 }
Christopher Ferrisff88fb02019-11-04 18:40:00 -08001119 dprintf(fd, "END\n");
Christopher Ferris2e1a40a2018-06-13 10:46:34 -07001120}
1121
1122bool debug_write_malloc_leak_info(FILE* fp) {
Christopher Ferrisff88fb02019-11-04 18:40:00 -08001123 // Make sure any pending output is written to the file.
1124 fflush(fp);
1125
Christopher Ferrisd269fcc2019-05-06 19:03:59 -07001126 ScopedConcurrentLock lock;
Christopher Ferris2e1a40a2018-06-13 10:46:34 -07001127 ScopedDisableDebugCalls disable;
Christopher Ferris9bf78172020-05-20 15:37:30 -07001128 ScopedBacktraceSignalBlocker blocked;
Christopher Ferris2e1a40a2018-06-13 10:46:34 -07001129
1130 std::lock_guard<std::mutex> guard(g_dump_lock);
1131
1132 if (!(g_debug->config().options() & BACKTRACE)) {
1133 return false;
1134 }
1135
Christopher Ferrisff88fb02019-11-04 18:40:00 -08001136 write_dump(fileno(fp));
1137
Christopher Ferris602b88c2017-08-04 13:04:04 -07001138 return true;
1139}
Christopher Ferris2e1a40a2018-06-13 10:46:34 -07001140
1141void debug_dump_heap(const char* file_name) {
Christopher Ferrisd269fcc2019-05-06 19:03:59 -07001142 ScopedConcurrentLock lock;
Christopher Ferris2e1a40a2018-06-13 10:46:34 -07001143 ScopedDisableDebugCalls disable;
Christopher Ferris9bf78172020-05-20 15:37:30 -07001144 ScopedBacktraceSignalBlocker blocked;
Christopher Ferris2e1a40a2018-06-13 10:46:34 -07001145
1146 std::lock_guard<std::mutex> guard(g_dump_lock);
1147
Christopher Ferrisff88fb02019-11-04 18:40:00 -08001148 int fd = open(file_name, O_RDWR | O_CREAT | O_NOFOLLOW | O_TRUNC | O_CLOEXEC, 0644);
1149 if (fd == -1) {
Christopher Ferris2e1a40a2018-06-13 10:46:34 -07001150 error_log("Unable to create file: %s", file_name);
1151 return;
1152 }
1153
1154 error_log("Dumping to file: %s\n", file_name);
Christopher Ferrisff88fb02019-11-04 18:40:00 -08001155 write_dump(fd);
1156 close(fd);
Christopher Ferris2e1a40a2018-06-13 10:46:34 -07001157}