Small refactor.
- Move all ScopedDisableDebugCalls into the debug_XXX calls. This avoids
any issues that might arise where every part of the code needs to properly
guard anything that might allocate. Instead everything is already guarded.
- Add a pointer to debug_data in all of the XXData classes. This avoids
calling individual functions passing in the debug_data pointer.
- Flip the NO_HEADER_OPTIONS to an explicit HEADER_OPTIONS list since fewer
options actually require a header.
- Move the extern of g_debug to the DebugData.h header.
Change-Id: Ia213a391b4a44d9ce122a709d09fe4f1b5426f36
diff --git a/libc/malloc_debug/BacktraceData.cpp b/libc/malloc_debug/BacktraceData.cpp
index 400e282..3d46bf0 100644
--- a/libc/malloc_debug/BacktraceData.cpp
+++ b/libc/malloc_debug/BacktraceData.cpp
@@ -41,27 +41,24 @@
#include "debug_log.h"
#include "malloc_debug.h"
-BacktraceData::BacktraceData(const Config& config, size_t* offset) {
+static void EnableToggle(int, siginfo_t*, void*) {
+ if (g_debug->backtrace->enabled()) {
+ g_debug->backtrace->set_enabled(false);
+ } else {
+ g_debug->backtrace->set_enabled(true);
+ }
+}
+
+BacktraceData::BacktraceData(DebugData* debug_data, const Config& config, size_t* offset)
+ : OptionData(debug_data) {
size_t hdr_len = sizeof(BacktraceHeader) + sizeof(uintptr_t) * config.backtrace_frames;
alloc_offset_ = *offset;
*offset += BIONIC_ALIGN(hdr_len, MINIMUM_ALIGNMENT_BYTES);
}
-static BacktraceData* g_backtrace_data = nullptr;
-
-static void EnableToggle(int, siginfo_t*, void*) {
- if (g_backtrace_data->enabled()) {
- g_backtrace_data->set_enabled(false);
- } else {
- g_backtrace_data->set_enabled(true);
- }
-}
-
bool BacktraceData::Initialize(const Config& config) {
enabled_ = config.backtrace_enabled;
if (config.backtrace_enable_on_signal) {
- g_backtrace_data = this;
-
struct sigaction enable_act;
memset(&enable_act, 0, sizeof(enable_act));
diff --git a/libc/malloc_debug/BacktraceData.h b/libc/malloc_debug/BacktraceData.h
index 842e372..dbc3989 100644
--- a/libc/malloc_debug/BacktraceData.h
+++ b/libc/malloc_debug/BacktraceData.h
@@ -33,12 +33,14 @@
#include <private/bionic_macros.h>
+#include "OptionData.h"
+
// Forward declarations.
struct Config;
-class BacktraceData {
+class BacktraceData : public OptionData {
public:
- BacktraceData(const Config& config, size_t* offset);
+ BacktraceData(DebugData* debug_data, const Config& config, size_t* offset);
virtual ~BacktraceData() = default;
bool Initialize(const Config& config);
diff --git a/libc/malloc_debug/Config.h b/libc/malloc_debug/Config.h
index cb1de5a..3ee93b2 100644
--- a/libc/malloc_debug/Config.h
+++ b/libc/malloc_debug/Config.h
@@ -49,8 +49,8 @@
constexpr size_t MINIMUM_ALIGNMENT_BYTES = 8;
#endif
-// If only one or more of these options is set, then no special header is needed.
-constexpr uint64_t NO_HEADER_OPTIONS = FILL_ON_ALLOC | FILL_ON_FREE | EXPAND_ALLOC;
+// If one or more of these options is set, then a special header is needed.
+constexpr uint64_t HEADER_OPTIONS = FRONT_GUARD | REAR_GUARD | BACKTRACE | FREE_TRACK | LEAK_TRACK;
struct Config {
bool SetFromProperties();
diff --git a/libc/malloc_debug/DebugData.cpp b/libc/malloc_debug/DebugData.cpp
index 0447566..58cbbcb 100644
--- a/libc/malloc_debug/DebugData.cpp
+++ b/libc/malloc_debug/DebugData.cpp
@@ -43,37 +43,37 @@
}
// Check to see if the options that require a header are enabled.
- if ((config_.options & ~(NO_HEADER_OPTIONS)) != 0) {
+ if (config_.options & HEADER_OPTIONS) {
need_header_ = true;
// Initialize all of the static header offsets.
pointer_offset_ = BIONIC_ALIGN(sizeof(Header), MINIMUM_ALIGNMENT_BYTES);
if (config_.options & BACKTRACE) {
- backtrace.reset(new BacktraceData(config_, &pointer_offset_));
+ backtrace.reset(new BacktraceData(this, config_, &pointer_offset_));
if (!backtrace->Initialize(config_)) {
return false;
}
}
if (config_.options & FRONT_GUARD) {
- front_guard.reset(new FrontGuardData(config_, &pointer_offset_));
+ front_guard.reset(new FrontGuardData(this, config_, &pointer_offset_));
}
extra_bytes_ = pointer_offset_;
// Initialize all of the non-header data.
if (config_.options & REAR_GUARD) {
- rear_guard.reset(new RearGuardData(config_));
+ rear_guard.reset(new RearGuardData(this, config_));
extra_bytes_ += config_.rear_guard_bytes;
}
if (config_.options & FREE_TRACK) {
- free_track.reset(new FreeTrackData(config_));
+ free_track.reset(new FreeTrackData(this, config_));
}
if (config_.options & TRACK_ALLOCS) {
- track.reset(new TrackData());
+ track.reset(new TrackData(this));
}
}
diff --git a/libc/malloc_debug/DebugData.h b/libc/malloc_debug/DebugData.h
index 4600b33..7e55512 100644
--- a/libc/malloc_debug/DebugData.h
+++ b/libc/malloc_debug/DebugData.h
@@ -103,4 +103,6 @@
DISALLOW_COPY_AND_ASSIGN(DebugData);
};
+extern DebugData* g_debug;
+
#endif // MALLOC_DEBUG_DEBUGDATA_H
diff --git a/libc/malloc_debug/FreeTrackData.cpp b/libc/malloc_debug/FreeTrackData.cpp
index ed41981..682f93d 100644
--- a/libc/malloc_debug/FreeTrackData.cpp
+++ b/libc/malloc_debug/FreeTrackData.cpp
@@ -36,19 +36,16 @@
#include "FreeTrackData.h"
#include "malloc_debug.h"
-FreeTrackData::FreeTrackData(const Config& config)
- : backtrace_num_frames_(config.free_track_backtrace_num_frames) {
+FreeTrackData::FreeTrackData(DebugData* debug, const Config& config)
+ : OptionData(debug), backtrace_num_frames_(config.free_track_backtrace_num_frames) {
cmp_mem_.resize(4096);
memset(cmp_mem_.data(), config.fill_free_value, cmp_mem_.size());
}
-void FreeTrackData::LogFreeError(DebugData& debug, const Header* header,
- const uint8_t* pointer) {
- ScopedDisableDebugCalls disable;
-
+void FreeTrackData::LogFreeError(const Header* header, const uint8_t* pointer) {
error_log(LOG_DIVIDER);
error_log("+++ ALLOCATION %p USED AFTER FREE", pointer);
- uint8_t fill_free_value = debug.config().fill_free_value;
+ uint8_t fill_free_value = debug_->config().fill_free_value;
for (size_t i = 0; i < header->usable_size; i++) {
if (pointer[i] != fill_free_value) {
error_log(" pointer[%zu] = 0x%02x (expected 0x%02x)", i, pointer[i], fill_free_value);
@@ -63,10 +60,8 @@
error_log(LOG_DIVIDER);
}
-void FreeTrackData::VerifyAndFree(DebugData& debug, const Header* header,
- const void* pointer) {
- ScopedDisableDebugCalls disable;
-
+void FreeTrackData::VerifyAndFree(const Header* header) {
+ const void* pointer = debug_->GetPointer(header);
if (header->tag != DEBUG_FREE_TAG) {
error_log(LOG_DIVIDER);
error_log("+++ ALLOCATION %p HAS CORRUPTED HEADER TAG 0x%x AFTER FREE", pointer, header->tag);
@@ -74,11 +69,12 @@
} else {
const uint8_t* memory = reinterpret_cast<const uint8_t*>(pointer);
size_t bytes = header->usable_size;
- bytes = (bytes < debug.config().fill_on_free_bytes) ? bytes : debug.config().fill_on_free_bytes;
+ bytes = (bytes < debug_->config().fill_on_free_bytes) ? bytes
+ : debug_->config().fill_on_free_bytes;
while (bytes > 0) {
size_t bytes_to_cmp = (bytes < cmp_mem_.size()) ? bytes : cmp_mem_.size();
if (memcmp(memory, cmp_mem_.data(), bytes_to_cmp) != 0) {
- LogFreeError(debug, header, reinterpret_cast<const uint8_t*>(pointer));
+ LogFreeError(header, reinterpret_cast<const uint8_t*>(pointer));
break;
}
bytes -= bytes_to_cmp;
@@ -94,14 +90,11 @@
g_dispatch->free(header->orig_pointer);
}
-void FreeTrackData::Add(DebugData& debug, const Header* header) {
- // Make sure the stl calls below don't call the debug_XXX functions.
- ScopedDisableDebugCalls disable;
-
+void FreeTrackData::Add(const Header* header) {
pthread_mutex_lock(&mutex_);
- if (list_.size() == debug.config().free_track_allocations) {
+ if (list_.size() == debug_->config().free_track_allocations) {
const Header* old_header = list_.back();
- VerifyAndFree(debug, old_header, debug.GetPointer(old_header));
+ VerifyAndFree(old_header);
list_.pop_back();
}
@@ -118,19 +111,14 @@
pthread_mutex_unlock(&mutex_);
}
-void FreeTrackData::VerifyAll(DebugData& debug) {
- // Make sure the stl calls below don't call the debug_XXX functions.
- ScopedDisableDebugCalls disable;
-
+void FreeTrackData::VerifyAll() {
for (const auto& header : list_) {
- VerifyAndFree(debug, header, debug.GetPointer(header));
+ VerifyAndFree(header);
}
list_.clear();
}
void FreeTrackData::LogBacktrace(const Header* header) {
- ScopedDisableDebugCalls disable;
-
auto back_iter = backtraces_.find(header);
if (back_iter == backtraces_.end()) {
return;
diff --git a/libc/malloc_debug/FreeTrackData.h b/libc/malloc_debug/FreeTrackData.h
index 804b5a6..21f845f 100644
--- a/libc/malloc_debug/FreeTrackData.h
+++ b/libc/malloc_debug/FreeTrackData.h
@@ -38,26 +38,28 @@
#include <private/bionic_macros.h>
-// Forward declarations.
-struct Header;
-class DebugData;
-struct Config;
-struct BacktraceHeader;
+#include "OptionData.h"
-class FreeTrackData {
+// Forward declarations.
+struct BacktraceHeader;
+struct Config;
+class DebugData;
+struct Header;
+
+class FreeTrackData : public OptionData {
public:
- FreeTrackData(const Config& config);
+ FreeTrackData(DebugData* debug_data, const Config& config);
virtual ~FreeTrackData() = default;
- void Add(DebugData& debug, const Header* header);
+ void Add(const Header* header);
- void VerifyAll(DebugData& debug);
+ void VerifyAll();
void LogBacktrace(const Header* header);
private:
- void LogFreeError(DebugData& debug, const Header* header, const uint8_t* pointer);
- void VerifyAndFree(DebugData& debug, const Header* header, const void* pointer);
+ void LogFreeError(const Header* header, const uint8_t* pointer);
+ void VerifyAndFree(const Header* header);
pthread_mutex_t mutex_ = PTHREAD_MUTEX_INITIALIZER;
std::deque<const Header*> list_;
diff --git a/libc/malloc_debug/GuardData.cpp b/libc/malloc_debug/GuardData.cpp
index c70e8f1..48961b6 100644
--- a/libc/malloc_debug/GuardData.cpp
+++ b/libc/malloc_debug/GuardData.cpp
@@ -39,15 +39,14 @@
#include "malloc_debug.h"
#include "GuardData.h"
-GuardData::GuardData(int init_value, size_t num_bytes) {
+GuardData::GuardData(DebugData* debug_data, int init_value, size_t num_bytes)
+ : OptionData(debug_data) {
// Create a buffer for fast comparisons of the front guard.
cmp_mem_.resize(num_bytes);
memset(cmp_mem_.data(), init_value, cmp_mem_.size());
}
void GuardData::LogFailure(const Header* header, const void* pointer, const void* data) {
- ScopedDisableDebugCalls disable;
-
error_log(LOG_DIVIDER);
error_log("+++ ALLOCATION %p SIZE %zu HAS A CORRUPTED %s GUARD", pointer,
header->real_size(), GetTypeName());
@@ -70,8 +69,8 @@
error_log(LOG_DIVIDER);
}
-FrontGuardData::FrontGuardData(const Config& config, size_t* offset)
- : GuardData(config.front_guard_value, config.front_guard_bytes) {
+FrontGuardData::FrontGuardData(DebugData* debug_data, const Config& config, size_t* offset)
+ : GuardData(debug_data, config.front_guard_value, config.front_guard_bytes) {
// Create a buffer for fast comparisons of the front guard.
cmp_mem_.resize(config.front_guard_bytes);
memset(cmp_mem_.data(), config.front_guard_value, cmp_mem_.size());
@@ -80,22 +79,22 @@
*offset += config.front_guard_bytes;
}
-bool FrontGuardData::Valid(DebugData& debug, const Header* header) {
- return GuardData::Valid(debug.GetFrontGuard(header));
+bool FrontGuardData::Valid(const Header* header) {
+ return GuardData::Valid(debug_->GetFrontGuard(header));
}
-void FrontGuardData::LogFailure(DebugData& debug, const Header* header) {
- GuardData::LogFailure(header, debug.GetPointer(header), debug.GetFrontGuard(header));
+void FrontGuardData::LogFailure(const Header* header) {
+ GuardData::LogFailure(header, debug_->GetPointer(header), debug_->GetFrontGuard(header));
}
-RearGuardData::RearGuardData(const Config& config)
- : GuardData(config.rear_guard_value, config.rear_guard_bytes) {
+RearGuardData::RearGuardData(DebugData* debug_data, const Config& config)
+ : GuardData(debug_data, config.rear_guard_value, config.rear_guard_bytes) {
}
-bool RearGuardData::Valid(DebugData& debug, const Header* header) {
- return GuardData::Valid(debug.GetRearGuard(header));
+bool RearGuardData::Valid(const Header* header) {
+ return GuardData::Valid(debug_->GetRearGuard(header));
}
-void RearGuardData::LogFailure(DebugData& debug, const Header* header) {
- GuardData::LogFailure(header, debug.GetPointer(header), debug.GetRearGuard(header));
+void RearGuardData::LogFailure(const Header* header) {
+ GuardData::LogFailure(header, debug_->GetPointer(header), debug_->GetRearGuard(header));
}
diff --git a/libc/malloc_debug/GuardData.h b/libc/malloc_debug/GuardData.h
index 4de2702..bfb3949 100644
--- a/libc/malloc_debug/GuardData.h
+++ b/libc/malloc_debug/GuardData.h
@@ -36,14 +36,16 @@
#include <private/bionic_macros.h>
+#include "OptionData.h"
+
// Forward declarations.
class DebugData;
struct Header;
struct Config;
-class GuardData {
+class GuardData : public OptionData {
public:
- GuardData(int init_value, size_t num_bytes);
+ GuardData(DebugData* debug_data, int init_value, size_t num_bytes);
virtual ~GuardData() = default;
bool Valid(void* data) { return memcmp(data, cmp_mem_.data(), cmp_mem_.size()) == 0; }
@@ -60,12 +62,12 @@
class FrontGuardData : public GuardData {
public:
- FrontGuardData(const Config& config, size_t* offset);
+ FrontGuardData(DebugData* debug_data, const Config& config, size_t* offset);
virtual ~FrontGuardData() = default;
- bool Valid(DebugData& debug, const Header* header);
+ bool Valid(const Header* header);
- void LogFailure(DebugData& debug, const Header* header);
+ void LogFailure(const Header* header);
size_t offset() { return offset_; }
@@ -79,12 +81,12 @@
class RearGuardData : public GuardData {
public:
- RearGuardData(const Config& config);
+ RearGuardData(DebugData* debug_data, const Config& config);
virtual ~RearGuardData() = default;
- bool Valid(DebugData& debug, const Header* header);
+ bool Valid(const Header* header);
- void LogFailure(DebugData& debug, const Header* header);
+ void LogFailure(const Header* header);
private:
const char* GetTypeName() override { return "REAR"; }
diff --git a/libc/malloc_debug/OptionData.h b/libc/malloc_debug/OptionData.h
new file mode 100644
index 0000000..80190f5
--- /dev/null
+++ b/libc/malloc_debug/OptionData.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef DEBUG_MALLOC_OPTIONDATA_H
+#define DEBUG_MALLOC_OPTIONDATA_H
+
+// Forward Declarations
+class DebugData;
+
+class OptionData {
+ public:
+ OptionData(DebugData* debug) : debug_(debug) {}
+ ~OptionData() = default;
+
+ protected:
+ DebugData* debug_;
+
+ DISALLOW_COPY_AND_ASSIGN(OptionData);
+};
+
+#endif // MALLOC_DEBUG_OPTIONDATA_H
diff --git a/libc/malloc_debug/TrackData.cpp b/libc/malloc_debug/TrackData.cpp
index c9828d0..18f428b 100644
--- a/libc/malloc_debug/TrackData.cpp
+++ b/libc/malloc_debug/TrackData.cpp
@@ -44,9 +44,10 @@
#include "malloc_debug.h"
#include "TrackData.h"
-void TrackData::GetList(std::vector<const Header*>* list) {
- ScopedDisableDebugCalls disable;
+TrackData::TrackData(DebugData* debug_data) : OptionData(debug_data) {
+}
+void TrackData::GetList(std::vector<const Header*>* list) {
for (const auto& header : headers_) {
list->push_back(header);
}
@@ -59,8 +60,6 @@
}
void TrackData::Add(const Header* header, bool backtrace_found) {
- ScopedDisableDebugCalls disable;
-
pthread_mutex_lock(&mutex_);
if (backtrace_found) {
total_backtrace_allocs_++;
@@ -70,8 +69,6 @@
}
void TrackData::Remove(const Header* header, bool backtrace_found) {
- ScopedDisableDebugCalls disable;
-
pthread_mutex_lock(&mutex_);
headers_.erase(header);
if (backtrace_found) {
@@ -81,26 +78,22 @@
}
bool TrackData::Contains(const Header* header) {
- ScopedDisableDebugCalls disable;
-
pthread_mutex_lock(&mutex_);
bool found = headers_.count(header);
pthread_mutex_unlock(&mutex_);
return found;
}
-void TrackData::DisplayLeaks(DebugData& debug) {
- ScopedDisableDebugCalls disable;
-
+void TrackData::DisplayLeaks() {
std::vector<const Header*> list;
GetList(&list);
size_t track_count = 0;
for (const auto& header : list) {
error_log("+++ %s leaked block of size %zu at %p (leak %zu of %zu)", getprogname(),
- header->real_size(), debug.GetPointer(header), ++track_count, list.size());
- if (debug.config().options & BACKTRACE) {
- BacktraceHeader* back_header = debug.GetAllocBacktrace(header);
+ header->real_size(), debug_->GetPointer(header), ++track_count, list.size());
+ if (debug_->config().options & BACKTRACE) {
+ BacktraceHeader* back_header = debug_->GetAllocBacktrace(header);
if (back_header->num_frames > 0) {
error_log("Backtrace at time of allocation:");
backtrace_log(&back_header->frames[0], back_header->num_frames);
@@ -110,15 +103,15 @@
}
}
-void TrackData::GetInfo(DebugData& debug, uint8_t** info, size_t* overall_size,
- size_t* info_size, size_t* total_memory, size_t* backtrace_size) {
+void TrackData::GetInfo(uint8_t** info, size_t* overall_size, size_t* info_size,
+ size_t* total_memory, size_t* backtrace_size) {
ScopedPthreadMutexLocker scoped(&mutex_);
if (headers_.size() == 0 || total_backtrace_allocs_ == 0) {
return;
}
- *backtrace_size = debug.config().backtrace_frames;
+ *backtrace_size = debug_->config().backtrace_frames;
*info_size = sizeof(size_t) * 2 + sizeof(uintptr_t) * *backtrace_size;
*info = reinterpret_cast<uint8_t*>(g_dispatch->calloc(*info_size, total_backtrace_allocs_));
if (*info == nullptr) {
@@ -131,7 +124,7 @@
uint8_t* data = *info;
for (const auto& header : list) {
- BacktraceHeader* back_header = debug.GetAllocBacktrace(header);
+ BacktraceHeader* back_header = debug_->GetAllocBacktrace(header);
if (back_header->num_frames > 0) {
memcpy(data, &header->size, sizeof(size_t));
memcpy(&data[sizeof(size_t)], &back_header->num_frames, sizeof(size_t));
diff --git a/libc/malloc_debug/TrackData.h b/libc/malloc_debug/TrackData.h
index 1234316..fcd8f2a 100644
--- a/libc/malloc_debug/TrackData.h
+++ b/libc/malloc_debug/TrackData.h
@@ -37,14 +37,16 @@
#include <private/bionic_macros.h>
+#include "OptionData.h"
+
// Forward declarations.
struct Header;
struct Config;
class DebugData;
-class TrackData {
+class TrackData : public OptionData {
public:
- TrackData() = default;
+ TrackData(DebugData* debug_data);
virtual ~TrackData() = default;
void GetList(std::vector<const Header*>* list);
@@ -55,10 +57,10 @@
bool Contains(const Header *header);
- void GetInfo(DebugData& debug, uint8_t** info, size_t* overall_size,
- size_t* info_size, size_t* total_memory, size_t* backtrace_size);
+ void GetInfo(uint8_t** info, size_t* overall_size, size_t* info_size,
+ size_t* total_memory, size_t* backtrace_size);
- void DisplayLeaks(DebugData& debug);
+ void DisplayLeaks();
void PrepareFork() { pthread_mutex_lock(&mutex_); }
void PostForkParent() { pthread_mutex_unlock(&mutex_); }
diff --git a/libc/malloc_debug/debug_disable.cpp b/libc/malloc_debug/debug_disable.cpp
index af0264b..b80ba8c 100644
--- a/libc/malloc_debug/debug_disable.cpp
+++ b/libc/malloc_debug/debug_disable.cpp
@@ -32,7 +32,6 @@
#include "debug_disable.h"
#include "debug_log.h"
-extern DebugData* g_debug;
pthread_key_t g_disable_key;
bool DebugCallsDisabled() {
diff --git a/libc/malloc_debug/malloc_debug.cpp b/libc/malloc_debug/malloc_debug.cpp
index 1ee7689..5da5b88 100644
--- a/libc/malloc_debug/malloc_debug.cpp
+++ b/libc/malloc_debug/malloc_debug.cpp
@@ -114,8 +114,6 @@
}
static void LogTagError(const Header* header, const void* pointer, const char* name) {
- ScopedDisableDebugCalls disable;
-
error_log(LOG_DIVIDER);
if (header->tag == DEBUG_FREE_TAG) {
error_log("+++ ALLOCATION %p USED AFTER FREE (%s)", pointer, name);
@@ -165,7 +163,6 @@
if (g_debug->config().options & BACKTRACE) {
BacktraceHeader* back_header = g_debug->GetAllocBacktrace(header);
if (g_debug->backtrace->enabled()) {
- ScopedDisableDebugCalls disable;
back_header->num_frames = backtrace_get(
&back_header->frames[0], g_debug->config().backtrace_frames);
backtrace_found = back_header->num_frames > 0;
@@ -217,11 +214,11 @@
}
if (g_debug->config().options & FREE_TRACK) {
- g_debug->free_track->VerifyAll(*g_debug);
+ g_debug->free_track->VerifyAll();
}
if (g_debug->config().options & LEAK_TRACK) {
- g_debug->track->DisplayLeaks(*g_debug);
+ g_debug->track->DisplayLeaks();
}
DebugDisableSet(true);
@@ -257,32 +254,37 @@
return;
}
- g_debug->track->GetInfo(*g_debug, info, overall_size, info_size, total_memory, backtrace_size);
+ g_debug->track->GetInfo(info, overall_size, info_size, total_memory, backtrace_size);
}
void debug_free_malloc_leak_info(uint8_t* info) {
g_dispatch->free(info);
}
-size_t debug_malloc_usable_size(void* pointer) {
- if (DebugCallsDisabled() || !g_debug->need_header() || pointer == nullptr) {
+static size_t internal_malloc_usable_size(void* pointer) {
+ if (g_debug->need_header()) {
+ Header* header = g_debug->GetHeader(pointer);
+ if (header->tag != DEBUG_TAG) {
+ LogTagError(header, pointer, "malloc_usable_size");
+ return 0;
+ }
+
+ return header->usable_size;
+ } else {
return g_dispatch->malloc_usable_size(pointer);
}
-
- Header* header = g_debug->GetHeader(pointer);
- if (header->tag != DEBUG_TAG) {
- LogTagError(header, pointer, "malloc_usable_size");
- return 0;
- }
-
- return header->usable_size;
}
-void* debug_malloc(size_t size) {
- if (DebugCallsDisabled()) {
- return g_dispatch->malloc(size);
+size_t debug_malloc_usable_size(void* pointer) {
+ if (DebugCallsDisabled() || pointer == nullptr) {
+ return g_dispatch->malloc_usable_size(pointer);
}
+ ScopedDisableDebugCalls disable;
+ return internal_malloc_usable_size(pointer);
+}
+
+static void *internal_malloc(size_t size) {
if (size == 0) {
size = 1;
}
@@ -312,7 +314,7 @@
}
if (pointer != nullptr && g_debug->config().options & FILL_ON_ALLOC) {
- size_t bytes = debug_malloc_usable_size(pointer);
+ size_t bytes = internal_malloc_usable_size(pointer);
size_t fill_bytes = g_debug->config().fill_on_alloc_bytes;
bytes = (bytes < fill_bytes) ? bytes : fill_bytes;
memset(pointer, g_debug->config().fill_alloc_value, bytes);
@@ -320,11 +322,16 @@
return pointer;
}
-void debug_free(void* pointer) {
- if (DebugCallsDisabled() || pointer == nullptr) {
- return g_dispatch->free(pointer);
+void* debug_malloc(size_t size) {
+ if (DebugCallsDisabled()) {
+ return g_dispatch->malloc(size);
}
+ ScopedDisableDebugCalls disable;
+ return internal_malloc(size);
+}
+
+static void internal_free(void* pointer) {
void* free_pointer = pointer;
size_t bytes;
Header* header;
@@ -337,13 +344,13 @@
free_pointer = header->orig_pointer;
if (g_debug->config().options & FRONT_GUARD) {
- if (!g_debug->front_guard->Valid(*g_debug, header)) {
- g_debug->front_guard->LogFailure(*g_debug, header);
+ if (!g_debug->front_guard->Valid(header)) {
+ g_debug->front_guard->LogFailure(header);
}
}
if (g_debug->config().options & REAR_GUARD) {
- if (!g_debug->rear_guard->Valid(*g_debug, header)) {
- g_debug->rear_guard->LogFailure(*g_debug, header);
+ if (!g_debug->rear_guard->Valid(header)) {
+ g_debug->rear_guard->LogFailure(header);
}
}
@@ -374,16 +381,26 @@
// frees at the same time and we wind up trying to really free this
// pointer from another thread, while still trying to free it in
// this function.
- g_debug->free_track->Add(*g_debug, header);
+ g_debug->free_track->Add(header);
} else {
g_dispatch->free(free_pointer);
}
}
+void debug_free(void* pointer) {
+ if (DebugCallsDisabled() || pointer == nullptr) {
+ return g_dispatch->free(pointer);
+ }
+ ScopedDisableDebugCalls disable;
+
+ internal_free(pointer);
+}
+
void* debug_memalign(size_t alignment, size_t bytes) {
if (DebugCallsDisabled()) {
return g_dispatch->memalign(alignment, bytes);
}
+ ScopedDisableDebugCalls disable;
if (bytes == 0) {
bytes = 1;
@@ -438,11 +455,12 @@
}
if (pointer != nullptr && g_debug->config().options & FILL_ON_ALLOC) {
- size_t bytes = debug_malloc_usable_size(pointer);
+ size_t bytes = internal_malloc_usable_size(pointer);
size_t fill_bytes = g_debug->config().fill_on_alloc_bytes;
bytes = (bytes < fill_bytes) ? bytes : fill_bytes;
memset(pointer, g_debug->config().fill_alloc_value, bytes);
}
+
return pointer;
}
@@ -450,13 +468,14 @@
if (DebugCallsDisabled()) {
return g_dispatch->realloc(pointer, bytes);
}
+ ScopedDisableDebugCalls disable;
if (pointer == nullptr) {
- return debug_malloc(bytes);
+ return internal_malloc(bytes);
}
if (bytes == 0) {
- debug_free(pointer);
+ internal_free(pointer);
return nullptr;
}
@@ -486,6 +505,7 @@
// Same size, do nothing.
if (real_size == header->real_size()) {
+ // Do not bother recording, this is essentially a nop.
return pointer;
}
@@ -502,11 +522,12 @@
memset(g_debug->GetRearGuard(header), g_debug->config().rear_guard_value,
g_debug->config().rear_guard_bytes);
}
+ // Do not bother recording, this is essentially a nop.
return pointer;
}
// Allocate the new size.
- new_pointer = debug_malloc(bytes);
+ new_pointer = internal_malloc(bytes);
if (new_pointer == nullptr) {
errno = ENOMEM;
return nullptr;
@@ -514,7 +535,7 @@
prev_size = header->usable_size;
memcpy(new_pointer, pointer, prev_size);
- debug_free(pointer);
+ internal_free(pointer);
} else {
prev_size = g_dispatch->malloc_usable_size(pointer);
new_pointer = g_dispatch->realloc(pointer, real_size);
@@ -524,7 +545,7 @@
}
if (g_debug->config().options & FILL_ON_ALLOC) {
- size_t bytes = debug_malloc_usable_size(new_pointer);
+ size_t bytes = internal_malloc_usable_size(new_pointer);
if (bytes > g_debug->config().fill_on_alloc_bytes) {
bytes = g_debug->config().fill_on_alloc_bytes;
}
@@ -541,6 +562,7 @@
if (DebugCallsDisabled()) {
return g_dispatch->calloc(nmemb, bytes);
}
+ ScopedDisableDebugCalls disable;
size_t size;
if (__builtin_mul_overflow(nmemb, bytes, &size)) {
@@ -645,6 +667,7 @@
if (DebugCallsDisabled() || pointer == nullptr) {
return 0;
}
+ ScopedDisableDebugCalls disable;
if (g_debug->need_header()) {
Header* header;