Add better free tracking.
Included in this change:
- Change the tag when a pointer is freed so it's easy to detect if
an already freed pointer is being used.
- Move the free backtrace out of the header. This backtrace is only
used under only some circumstances, so no need to allocate space
in all headers for it.
- Add new option free_track_backtrace_num_frames to specify how many
frames to record when the free occurs. This removes the dependency
on the backtrace option to get backtraces.
Bug: 26739265
Change-Id: I76f5209507dcf46af67ada162a7cb2bf282116f2
diff --git a/libc/malloc_debug/malloc_debug.cpp b/libc/malloc_debug/malloc_debug.cpp
index f55d488..4f86579 100644
--- a/libc/malloc_debug/malloc_debug.cpp
+++ b/libc/malloc_debug/malloc_debug.cpp
@@ -88,7 +88,14 @@
ScopedDisableDebugCalls disable;
error_log(LOG_DIVIDER);
- error_log("+++ ALLOCATION %p HAS INVALID TAG %" PRIx32 " (%s)", pointer, header->tag, name);
+ if (header->tag == DEBUG_FREE_TAG) {
+ error_log("+++ ALLOCATION %p USED AFTER FREE (%s)", pointer, name);
+ if (g_debug->config().options & FREE_TRACK) {
+ g_debug->free_track->LogBacktrace(header);
+ }
+ } else {
+ error_log("+++ ALLOCATION %p HAS INVALID TAG %" PRIx32 " (%s)", pointer, header->tag, name);
+ }
error_log("Backtrace at time of failure:");
std::vector<uintptr_t> frames(64);
size_t frame_num = backtrace_get(frames.data(), frames.size());
@@ -129,14 +136,12 @@
if (g_debug->config().options & BACKTRACE) {
BacktraceHeader* back_header = g_debug->GetAllocBacktrace(header);
if (g_debug->backtrace->enabled()) {
- back_header->num_frames = backtrace_get(&back_header->frames[0],
- g_debug->config().backtrace_frames);
+ back_header->num_frames = backtrace_get(
+ &back_header->frames[0], g_debug->config().backtrace_frames);
backtrace_found = back_header->num_frames > 0;
} else {
back_header->num_frames = 0;
}
- back_header = g_debug->GetFreeBacktrace(header);
- back_header->num_frames = 0;
}
if (g_debug->config().options & TRACK_ALLOCS) {
@@ -313,18 +318,12 @@
}
if (g_debug->config().options & FREE_TRACK) {
- // Only log the free backtrace if we are using the free track feature.
- if ((g_debug->config().options & BACKTRACE) && g_debug->backtrace->enabled()) {
- BacktraceHeader* back_header = g_debug->GetFreeBacktrace(header);
- back_header->num_frames = backtrace_get(&back_header->frames[0],
- g_debug->config().backtrace_frames);
- }
-
g_debug->free_track->Add(*g_debug, header);
// Do not free this pointer just yet.
free_pointer = nullptr;
}
+ header->tag = DEBUG_FREE_TAG;
bytes = header->usable_size;
} else {