Merge "Mangle the pointers stored in PointerData."
diff --git a/libc/malloc_debug/PointerData.cpp b/libc/malloc_debug/PointerData.cpp
index b982c0a..eaa0eb7 100644
--- a/libc/malloc_debug/PointerData.cpp
+++ b/libc/malloc_debug/PointerData.cpp
@@ -35,6 +35,7 @@
#include <sys/types.h>
#include <unistd.h>
+#include <functional>
#include <mutex>
#include <string>
#include <unordered_map>
@@ -195,40 +196,41 @@
}
void PointerData::Add(const void* ptr, size_t pointer_size) {
- uintptr_t pointer = reinterpret_cast<uintptr_t>(ptr);
size_t hash_index = 0;
if (backtrace_enabled_) {
hash_index = AddBacktrace(g_debug->config().backtrace_frames());
}
std::lock_guard<std::mutex> pointer_guard(pointer_mutex_);
- pointers_[pointer] = PointerInfoType{PointerInfoType::GetEncodedSize(pointer_size), hash_index};
+ uintptr_t mangled_ptr = ManglePointer(reinterpret_cast<uintptr_t>(ptr));
+ pointers_[mangled_ptr] =
+ PointerInfoType{PointerInfoType::GetEncodedSize(pointer_size), hash_index};
}
void PointerData::Remove(const void* ptr) {
- uintptr_t pointer = reinterpret_cast<uintptr_t>(ptr);
size_t hash_index;
{
std::lock_guard<std::mutex> pointer_guard(pointer_mutex_);
- auto entry = pointers_.find(pointer);
+ uintptr_t mangled_ptr = ManglePointer(reinterpret_cast<uintptr_t>(ptr));
+ auto entry = pointers_.find(mangled_ptr);
if (entry == pointers_.end()) {
// Attempt to remove unknown pointer.
- error_log("No tracked pointer found for 0x%" PRIxPTR, pointer);
+ error_log("No tracked pointer found for 0x%" PRIxPTR, DemanglePointer(mangled_ptr));
return;
}
hash_index = entry->second.hash_index;
- pointers_.erase(pointer);
+ pointers_.erase(mangled_ptr);
}
RemoveBacktrace(hash_index);
}
size_t PointerData::GetFrames(const void* ptr, uintptr_t* frames, size_t max_frames) {
- uintptr_t pointer = reinterpret_cast<uintptr_t>(ptr);
size_t hash_index;
{
std::lock_guard<std::mutex> pointer_guard(pointer_mutex_);
- auto entry = pointers_.find(pointer);
+ uintptr_t mangled_ptr = ManglePointer(reinterpret_cast<uintptr_t>(ptr));
+ auto entry = pointers_.find(mangled_ptr);
if (entry == pointers_.end()) {
return 0;
}
@@ -274,7 +276,8 @@
void PointerData::LogFreeError(const FreePointerInfoType& info, size_t max_cmp_bytes) {
error_log(LOG_DIVIDER);
- uint8_t* memory = reinterpret_cast<uint8_t*>(info.pointer);
+ uintptr_t pointer = DemanglePointer(info.mangled_ptr);
+ uint8_t* memory = reinterpret_cast<uint8_t*>(pointer);
error_log("+++ ALLOCATION %p USED AFTER FREE", memory);
uint8_t fill_free_value = g_debug->config().fill_free_value();
for (size_t i = 0; i < max_cmp_bytes; i++) {
@@ -296,13 +299,14 @@
void PointerData::VerifyFreedPointer(const FreePointerInfoType& info) {
size_t usable_size;
+ uintptr_t pointer = DemanglePointer(info.mangled_ptr);
if (g_debug->HeaderEnabled()) {
// Check to see if the tag data has been damaged.
- Header* header = g_debug->GetHeader(reinterpret_cast<const void*>(info.pointer));
+ Header* header = g_debug->GetHeader(reinterpret_cast<const void*>(pointer));
if (header->tag != DEBUG_FREE_TAG) {
error_log(LOG_DIVIDER);
- error_log("+++ ALLOCATION 0x%" PRIxPTR " HAS CORRUPTED HEADER TAG 0x%x AFTER FREE",
- info.pointer, header->tag);
+ error_log("+++ ALLOCATION 0x%" PRIxPTR " HAS CORRUPTED HEADER TAG 0x%x AFTER FREE", pointer,
+ header->tag);
error_log(LOG_DIVIDER);
if (g_debug->config().options() & ABORT_ON_ERROR) {
abort();
@@ -314,14 +318,14 @@
}
usable_size = header->usable_size;
} else {
- usable_size = g_dispatch->malloc_usable_size(reinterpret_cast<const void*>(info.pointer));
+ usable_size = g_dispatch->malloc_usable_size(reinterpret_cast<const void*>(pointer));
}
size_t bytes = (usable_size < g_debug->config().fill_on_free_bytes())
? usable_size
: g_debug->config().fill_on_free_bytes();
size_t max_cmp_bytes = bytes;
- const uint8_t* memory = reinterpret_cast<const uint8_t*>(info.pointer);
+ const uint8_t* memory = reinterpret_cast<const uint8_t*>(pointer);
while (bytes > 0) {
size_t bytes_to_cmp = (bytes < g_cmp_mem.size()) ? bytes : g_cmp_mem.size();
if (memcmp(memory, g_cmp_mem.data(), bytes_to_cmp) != 0) {
@@ -333,8 +337,6 @@
}
void* PointerData::AddFreed(const void* ptr) {
- uintptr_t pointer = reinterpret_cast<uintptr_t>(ptr);
-
size_t hash_index = 0;
size_t num_frames = g_debug->config().free_track_backtrace_num_frames();
if (num_frames) {
@@ -348,10 +350,11 @@
free_pointers_.pop_front();
VerifyFreedPointer(info);
RemoveBacktrace(info.hash_index);
- last = reinterpret_cast<void*>(info.pointer);
+ last = reinterpret_cast<void*>(DemanglePointer(info.mangled_ptr));
}
- free_pointers_.emplace_back(FreePointerInfoType{pointer, hash_index});
+ uintptr_t mangled_ptr = ManglePointer(reinterpret_cast<uintptr_t>(ptr));
+ free_pointers_.emplace_back(FreePointerInfoType{mangled_ptr, hash_index});
return last;
}
@@ -361,7 +364,7 @@
uintptr_t pointer = reinterpret_cast<uintptr_t>(ptr);
std::lock_guard<std::mutex> freed_guard(free_pointer_mutex_);
for (const auto& info : free_pointers_) {
- if (info.pointer == pointer) {
+ if (DemanglePointer(info.mangled_ptr) == pointer) {
hash_index = info.hash_index;
break;
}
@@ -388,6 +391,7 @@
for (const auto& entry : pointers_) {
FrameInfoType* frame_info = nullptr;
std::vector<unwindstack::FrameData>* backtrace_info = nullptr;
+ uintptr_t pointer = DemanglePointer(entry.first);
size_t hash_index = entry.second.hash_index;
if (hash_index > kBacktraceEmptyIndex) {
auto frame_entry = frames_.find(hash_index);
@@ -397,7 +401,7 @@
// occurs after the hash_index and frame data have been added.
// When removing a pointer, the pointer is deleted before the frame
// data.
- error_log("Pointer 0x%" PRIxPTR " hash_index %zu does not exist.", entry.first, hash_index);
+ error_log("Pointer 0x%" PRIxPTR " hash_index %zu does not exist.", pointer, hash_index);
} else {
frame_info = &frame_entry->second;
}
@@ -405,7 +409,7 @@
if (g_debug->config().options() & BACKTRACE_FULL) {
auto backtrace_entry = backtraces_info_.find(hash_index);
if (backtrace_entry == backtraces_info_.end()) {
- error_log("Pointer 0x%" PRIxPTR " hash_index %zu does not exist.", entry.first, hash_index);
+ error_log("Pointer 0x%" PRIxPTR " hash_index %zu does not exist.", pointer, hash_index);
} else {
backtrace_info = &backtrace_entry->second;
}
@@ -415,7 +419,7 @@
continue;
}
- list->emplace_back(ListInfoType{entry.first, 1, entry.second.RealSize(),
+ list->emplace_back(ListInfoType{pointer, 1, entry.second.RealSize(),
entry.second.ZygoteChildAlloc(), frame_info, backtrace_info});
}
@@ -550,9 +554,9 @@
}
bool PointerData::Exists(const void* ptr) {
- uintptr_t pointer = reinterpret_cast<uintptr_t>(ptr);
std::lock_guard<std::mutex> pointer_guard(pointer_mutex_);
- return pointers_.count(pointer) != 0;
+ uintptr_t mangled_ptr = ManglePointer(reinterpret_cast<uintptr_t>(ptr));
+ return pointers_.count(mangled_ptr) != 0;
}
void PointerData::DumpLiveToFile(int fd) {
@@ -637,3 +641,10 @@
free_pointer_mutex_.try_lock();
free_pointer_mutex_.unlock();
}
+
+void PointerData::IteratePointers(std::function<void(uintptr_t pointer)> fn) {
+ std::lock_guard<std::mutex> pointer_guard(pointer_mutex_);
+ for (const auto entry : pointers_) {
+ fn(DemanglePointer(entry.first));
+ }
+}
diff --git a/libc/malloc_debug/PointerData.h b/libc/malloc_debug/PointerData.h
index 92d2653..97eec0a 100644
--- a/libc/malloc_debug/PointerData.h
+++ b/libc/malloc_debug/PointerData.h
@@ -33,6 +33,7 @@
#include <atomic>
#include <deque>
+#include <functional>
#include <mutex>
#include <string>
#include <unordered_map>
@@ -99,7 +100,7 @@
};
struct FreePointerInfoType {
- uintptr_t pointer;
+ uintptr_t mangled_ptr;
size_t hash_index;
};
@@ -134,16 +135,14 @@
void PostForkParent();
void PostForkChild();
+ static void IteratePointers(std::function<void(uintptr_t pointer)> fn);
+
static size_t AddBacktrace(size_t num_frames);
static void RemoveBacktrace(size_t hash_index);
static void Add(const void* pointer, size_t size);
static void Remove(const void* pointer);
- typedef std::unordered_map<uintptr_t, PointerInfoType>::iterator iterator;
- static iterator begin() { return pointers_.begin(); }
- static iterator end() { return pointers_.end(); }
-
static void* AddFreed(const void* pointer);
static void LogFreeError(const FreePointerInfoType& info, size_t usable_size);
static void LogFreeBacktrace(const void* ptr);
@@ -162,6 +161,12 @@
static bool Exists(const void* pointer);
private:
+ // Only keep mangled pointers in internal data structures. This avoids
+ // problems where libmemunreachable finds these pointers and thinks they
+ // are not unreachable.
+ static inline uintptr_t ManglePointer(uintptr_t pointer) { return pointer ^ UINTPTR_MAX; }
+ static inline uintptr_t DemanglePointer(uintptr_t pointer) { return pointer ^ UINTPTR_MAX; }
+
static std::string GetHashString(uintptr_t* frames, size_t num_frames);
static void LogBacktrace(size_t hash_index);
diff --git a/libc/malloc_debug/malloc_debug.cpp b/libc/malloc_debug/malloc_debug.cpp
index 9f38946..d608f5d 100644
--- a/libc/malloc_debug/malloc_debug.cpp
+++ b/libc/malloc_debug/malloc_debug.cpp
@@ -890,10 +890,9 @@
void* arg) {
ScopedConcurrentLock lock;
if (g_debug->TrackPointers()) {
- // Since malloc is disabled, don't bother acquiring any locks.
- for (auto it = PointerData::begin(); it != PointerData::end(); ++it) {
- callback(it->first, InternalMallocUsableSize(reinterpret_cast<void*>(it->first)), arg);
- }
+ PointerData::IteratePointers([&callback, &arg](uintptr_t pointer) {
+ callback(pointer, InternalMallocUsableSize(reinterpret_cast<void*>(pointer)), arg);
+ });
return 0;
}