Merge "Add the timestamps for each alloc data"
This commit is contained in:
commit
08af69ab7f
4 changed files with 257 additions and 99 deletions
|
@ -28,6 +28,7 @@
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <inttypes.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <stdatomic.h>
|
#include <stdatomic.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
@ -52,40 +53,51 @@ bool ThreadCompleteEntry::Write(int fd) const {
|
||||||
return dprintf(fd, "%d: thread_done 0x0\n", tid_) > 0;
|
return dprintf(fd, "%d: thread_done 0x0\n", tid_) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
AllocEntry::AllocEntry(void* pointer) : pointer_(pointer) {}
|
AllocEntry::AllocEntry(void* pointer, uint64_t start_ns, uint64_t end_ns)
|
||||||
|
: pointer_(pointer), start_ns_(start_ns), end_ns_(end_ns) {}
|
||||||
|
|
||||||
MallocEntry::MallocEntry(void* pointer, size_t size) : AllocEntry(pointer), size_(size) {}
|
MallocEntry::MallocEntry(void* pointer, size_t size, uint64_t start_ns, uint64_t end_ns)
|
||||||
|
: AllocEntry(pointer, start_ns, end_ns), size_(size) {}
|
||||||
|
|
||||||
bool MallocEntry::Write(int fd) const {
|
bool MallocEntry::Write(int fd) const {
|
||||||
return dprintf(fd, "%d: malloc %p %zu\n", tid_, pointer_, size_) > 0;
|
return dprintf(fd, "%d: malloc %p %zu %" PRIu64 " %" PRIu64 "\n", tid_, pointer_, size_,
|
||||||
|
start_ns_, end_ns_) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
FreeEntry::FreeEntry(void* pointer) : AllocEntry(pointer) {}
|
FreeEntry::FreeEntry(void* pointer, uint64_t start_ns, uint64_t end_ns)
|
||||||
|
: AllocEntry(pointer, start_ns, end_ns) {}
|
||||||
|
|
||||||
bool FreeEntry::Write(int fd) const {
|
bool FreeEntry::Write(int fd) const {
|
||||||
return dprintf(fd, "%d: free %p\n", tid_, pointer_) > 0;
|
return dprintf(fd, "%d: free %p %" PRIu64 " %" PRIu64 "\n", tid_, pointer_, start_ns_, end_ns_) >
|
||||||
|
0;
|
||||||
}
|
}
|
||||||
|
|
||||||
CallocEntry::CallocEntry(void* pointer, size_t nmemb, size_t size)
|
CallocEntry::CallocEntry(void* pointer, size_t nmemb, size_t size, uint64_t start_ns,
|
||||||
: MallocEntry(pointer, size), nmemb_(nmemb) {}
|
uint64_t end_ns)
|
||||||
|
: MallocEntry(pointer, size, start_ns, end_ns), nmemb_(nmemb) {}
|
||||||
|
|
||||||
bool CallocEntry::Write(int fd) const {
|
bool CallocEntry::Write(int fd) const {
|
||||||
return dprintf(fd, "%d: calloc %p %zu %zu\n", tid_, pointer_, nmemb_, size_) > 0;
|
return dprintf(fd, "%d: calloc %p %zu %zu %" PRIu64 " %" PRIu64 "\n", tid_, pointer_, nmemb_,
|
||||||
|
size_, start_ns_, end_ns_) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ReallocEntry::ReallocEntry(void* pointer, size_t size, void* old_pointer)
|
ReallocEntry::ReallocEntry(void* pointer, size_t size, void* old_pointer, uint64_t start_ns,
|
||||||
: MallocEntry(pointer, size), old_pointer_(old_pointer) {}
|
uint64_t end_ns)
|
||||||
|
: MallocEntry(pointer, size, start_ns, end_ns), old_pointer_(old_pointer) {}
|
||||||
|
|
||||||
bool ReallocEntry::Write(int fd) const {
|
bool ReallocEntry::Write(int fd) const {
|
||||||
return dprintf(fd, "%d: realloc %p %p %zu\n", tid_, pointer_, old_pointer_, size_) > 0;
|
return dprintf(fd, "%d: realloc %p %p %zu %" PRIu64 " %" PRIu64 "\n", tid_, pointer_,
|
||||||
|
old_pointer_, size_, start_ns_, end_ns_) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// aligned_alloc, posix_memalign, memalign, pvalloc, valloc all recorded with this class.
|
// aligned_alloc, posix_memalign, memalign, pvalloc, valloc all recorded with this class.
|
||||||
MemalignEntry::MemalignEntry(void* pointer, size_t size, size_t alignment)
|
MemalignEntry::MemalignEntry(void* pointer, size_t size, size_t alignment, uint64_t start_ns,
|
||||||
: MallocEntry(pointer, size), alignment_(alignment) {}
|
uint64_t end_ns)
|
||||||
|
: MallocEntry(pointer, size, start_ns, end_ns), alignment_(alignment) {}
|
||||||
|
|
||||||
bool MemalignEntry::Write(int fd) const {
|
bool MemalignEntry::Write(int fd) const {
|
||||||
return dprintf(fd, "%d: memalign %p %zu %zu\n", tid_, pointer_, alignment_, size_) > 0;
|
return dprintf(fd, "%d: memalign %p %zu %zu %" PRIu64 " %" PRIu64 "\n", tid_, pointer_,
|
||||||
|
alignment_, size_, start_ns_, end_ns_) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ThreadData {
|
struct ThreadData {
|
||||||
|
|
|
@ -68,19 +68,23 @@ class ThreadCompleteEntry : public RecordEntry {
|
||||||
|
|
||||||
class AllocEntry : public RecordEntry {
|
class AllocEntry : public RecordEntry {
|
||||||
public:
|
public:
|
||||||
explicit AllocEntry(void* pointer);
|
explicit AllocEntry(void* pointer, uint64_t st, uint64_t et);
|
||||||
virtual ~AllocEntry() = default;
|
virtual ~AllocEntry() = default;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void* pointer_;
|
void* pointer_;
|
||||||
|
|
||||||
|
// The start/end time of this operation.
|
||||||
|
uint64_t start_ns_;
|
||||||
|
uint64_t end_ns_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BIONIC_DISALLOW_COPY_AND_ASSIGN(AllocEntry);
|
BIONIC_DISALLOW_COPY_AND_ASSIGN(AllocEntry);
|
||||||
};
|
};
|
||||||
|
|
||||||
class MallocEntry : public AllocEntry {
|
class MallocEntry : public AllocEntry {
|
||||||
public:
|
public:
|
||||||
MallocEntry(void* pointer, size_t size);
|
MallocEntry(void* pointer, size_t size, uint64_t st, uint64_t et);
|
||||||
virtual ~MallocEntry() = default;
|
virtual ~MallocEntry() = default;
|
||||||
|
|
||||||
bool Write(int fd) const override;
|
bool Write(int fd) const override;
|
||||||
|
@ -94,7 +98,7 @@ class MallocEntry : public AllocEntry {
|
||||||
|
|
||||||
class FreeEntry : public AllocEntry {
|
class FreeEntry : public AllocEntry {
|
||||||
public:
|
public:
|
||||||
explicit FreeEntry(void* pointer);
|
explicit FreeEntry(void* pointer, uint64_t st, uint64_t et);
|
||||||
virtual ~FreeEntry() = default;
|
virtual ~FreeEntry() = default;
|
||||||
|
|
||||||
bool Write(int fd) const override;
|
bool Write(int fd) const override;
|
||||||
|
@ -105,7 +109,7 @@ class FreeEntry : public AllocEntry {
|
||||||
|
|
||||||
class CallocEntry : public MallocEntry {
|
class CallocEntry : public MallocEntry {
|
||||||
public:
|
public:
|
||||||
CallocEntry(void* pointer, size_t size, size_t nmemb);
|
CallocEntry(void* pointer, size_t size, size_t nmemb, uint64_t st, uint64_t et);
|
||||||
virtual ~CallocEntry() = default;
|
virtual ~CallocEntry() = default;
|
||||||
|
|
||||||
bool Write(int fd) const override;
|
bool Write(int fd) const override;
|
||||||
|
@ -119,7 +123,7 @@ class CallocEntry : public MallocEntry {
|
||||||
|
|
||||||
class ReallocEntry : public MallocEntry {
|
class ReallocEntry : public MallocEntry {
|
||||||
public:
|
public:
|
||||||
ReallocEntry(void* pointer, size_t size, void* old_pointer);
|
ReallocEntry(void* pointer, size_t size, void* old_pointer, uint64_t st, uint64_t et);
|
||||||
virtual ~ReallocEntry() = default;
|
virtual ~ReallocEntry() = default;
|
||||||
|
|
||||||
bool Write(int fd) const override;
|
bool Write(int fd) const override;
|
||||||
|
@ -134,7 +138,7 @@ class ReallocEntry : public MallocEntry {
|
||||||
// aligned_alloc, posix_memalign, memalign, pvalloc, valloc all recorded with this class.
|
// aligned_alloc, posix_memalign, memalign, pvalloc, valloc all recorded with this class.
|
||||||
class MemalignEntry : public MallocEntry {
|
class MemalignEntry : public MallocEntry {
|
||||||
public:
|
public:
|
||||||
MemalignEntry(void* pointer, size_t size, size_t alignment);
|
MemalignEntry(void* pointer, size_t size, size_t alignment, uint64_t st, uint64_t et);
|
||||||
virtual ~MemalignEntry() = default;
|
virtual ~MemalignEntry() = default;
|
||||||
|
|
||||||
bool Write(int fd) const override;
|
bool Write(int fd) const override;
|
||||||
|
|
|
@ -68,6 +68,100 @@ DebugData* g_debug;
|
||||||
bool* g_zygote_child;
|
bool* g_zygote_child;
|
||||||
|
|
||||||
const MallocDispatch* g_dispatch;
|
const MallocDispatch* g_dispatch;
|
||||||
|
|
||||||
|
static __always_inline uint64_t Nanotime() {
|
||||||
|
struct timespec t = {};
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &t);
|
||||||
|
return static_cast<uint64_t>(t.tv_sec) * 1000000000LL + t.tv_nsec;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
// A TimedResult contains the result of from malloc end_ns al. functions and the
|
||||||
|
// start/end timestamps.
|
||||||
|
struct TimedResult {
|
||||||
|
uint64_t start_ns = 0;
|
||||||
|
uint64_t end_ns = 0;
|
||||||
|
union {
|
||||||
|
size_t s;
|
||||||
|
int i;
|
||||||
|
void* p;
|
||||||
|
} v;
|
||||||
|
|
||||||
|
uint64_t GetStartTimeNS() const { return start_ns; }
|
||||||
|
uint64_t GetEndTimeNS() const { return end_ns; }
|
||||||
|
void SetStartTimeNS(uint64_t t) { start_ns = t; }
|
||||||
|
void SetEndTimeNS(uint64_t t) { end_ns = t; }
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void setValue(T);
|
||||||
|
template <>
|
||||||
|
void setValue(size_t s) {
|
||||||
|
v.s = s;
|
||||||
|
}
|
||||||
|
template <>
|
||||||
|
void setValue(int i) {
|
||||||
|
v.i = i;
|
||||||
|
}
|
||||||
|
template <>
|
||||||
|
void setValue(void* p) {
|
||||||
|
v.p = p;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T getValue() const;
|
||||||
|
template <>
|
||||||
|
size_t getValue<size_t>() const {
|
||||||
|
return v.s;
|
||||||
|
}
|
||||||
|
template <>
|
||||||
|
int getValue<int>() const {
|
||||||
|
return v.i;
|
||||||
|
}
|
||||||
|
template <>
|
||||||
|
void* getValue<void*>() const {
|
||||||
|
return v.p;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class ScopedTimer {
|
||||||
|
public:
|
||||||
|
ScopedTimer(TimedResult& res) : res_(res) { res_.start_ns = Nanotime(); }
|
||||||
|
|
||||||
|
~ScopedTimer() { res_.end_ns = Nanotime(); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
TimedResult& res_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
template <typename MallocFn, typename... Args>
|
||||||
|
static TimedResult TimerCall(MallocFn fn, Args... args) {
|
||||||
|
TimedResult ret;
|
||||||
|
decltype((g_dispatch->*fn)(args...)) r;
|
||||||
|
if (g_debug->config().options() & RECORD_ALLOCS) {
|
||||||
|
ScopedTimer t(ret);
|
||||||
|
r = (g_dispatch->*fn)(args...);
|
||||||
|
} else {
|
||||||
|
r = (g_dispatch->*fn)(args...);
|
||||||
|
}
|
||||||
|
ret.setValue<decltype(r)>(r);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename MallocFn, typename... Args>
|
||||||
|
static TimedResult TimerCallVoid(MallocFn fn, Args... args) {
|
||||||
|
TimedResult ret;
|
||||||
|
{
|
||||||
|
ScopedTimer t(ret);
|
||||||
|
(g_dispatch->*fn)(args...);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define TCALL(FUNC, ...) TimerCall(&MallocDispatch::FUNC, __VA_ARGS__);
|
||||||
|
#define TCALLVOID(FUNC, ...) TimerCallVoid(&MallocDispatch::FUNC, __VA_ARGS__);
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
@ -419,7 +513,7 @@ size_t debug_malloc_usable_size(void* pointer) {
|
||||||
return InternalMallocUsableSize(pointer);
|
return InternalMallocUsableSize(pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void* InternalMalloc(size_t size) {
|
static TimedResult InternalMalloc(size_t size) {
|
||||||
if ((g_debug->config().options() & BACKTRACE) && g_debug->pointer->ShouldDumpAndReset()) {
|
if ((g_debug->config().options() & BACKTRACE) && g_debug->pointer->ShouldDumpAndReset()) {
|
||||||
debug_dump_heap(android::base::StringPrintf(
|
debug_dump_heap(android::base::StringPrintf(
|
||||||
"%s.%d.txt", g_debug->config().backtrace_dump_prefix().c_str(), getpid())
|
"%s.%d.txt", g_debug->config().backtrace_dump_prefix().c_str(), getpid())
|
||||||
|
@ -430,30 +524,35 @@ static void* InternalMalloc(size_t size) {
|
||||||
size = 1;
|
size = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TimedResult result;
|
||||||
|
|
||||||
size_t real_size = size + g_debug->extra_bytes();
|
size_t real_size = size + g_debug->extra_bytes();
|
||||||
if (real_size < size) {
|
if (real_size < size) {
|
||||||
// Overflow.
|
// Overflow.
|
||||||
errno = ENOMEM;
|
errno = ENOMEM;
|
||||||
return nullptr;
|
result.setValue<void*>(nullptr);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size > PointerInfoType::MaxSize()) {
|
if (size > PointerInfoType::MaxSize()) {
|
||||||
errno = ENOMEM;
|
errno = ENOMEM;
|
||||||
return nullptr;
|
result.setValue<void*>(nullptr);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* pointer;
|
|
||||||
if (g_debug->HeaderEnabled()) {
|
if (g_debug->HeaderEnabled()) {
|
||||||
Header* header =
|
result = TCALL(memalign, MINIMUM_ALIGNMENT_BYTES, real_size);
|
||||||
reinterpret_cast<Header*>(g_dispatch->memalign(MINIMUM_ALIGNMENT_BYTES, real_size));
|
Header* header = reinterpret_cast<Header*>(result.getValue<void*>());
|
||||||
if (header == nullptr) {
|
if (header == nullptr) {
|
||||||
return nullptr;
|
return result;
|
||||||
}
|
}
|
||||||
pointer = InitHeader(header, header, size);
|
result.setValue<void*>(InitHeader(header, header, size));
|
||||||
} else {
|
} else {
|
||||||
pointer = g_dispatch->malloc(real_size);
|
result = TCALL(malloc, real_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* pointer = result.getValue<void*>();
|
||||||
|
|
||||||
if (pointer != nullptr) {
|
if (pointer != nullptr) {
|
||||||
if (g_debug->TrackPointers()) {
|
if (g_debug->TrackPointers()) {
|
||||||
PointerData::Add(pointer, size);
|
PointerData::Add(pointer, size);
|
||||||
|
@ -466,7 +565,8 @@ static void* InternalMalloc(size_t size) {
|
||||||
memset(pointer, g_debug->config().fill_alloc_value(), bytes);
|
memset(pointer, g_debug->config().fill_alloc_value(), bytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return pointer;
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* debug_malloc(size_t size) {
|
void* debug_malloc(size_t size) {
|
||||||
|
@ -479,16 +579,17 @@ void* debug_malloc(size_t size) {
|
||||||
ScopedDisableDebugCalls disable;
|
ScopedDisableDebugCalls disable;
|
||||||
ScopedBacktraceSignalBlocker blocked;
|
ScopedBacktraceSignalBlocker blocked;
|
||||||
|
|
||||||
void* pointer = InternalMalloc(size);
|
TimedResult result = InternalMalloc(size);
|
||||||
|
|
||||||
if (g_debug->config().options() & RECORD_ALLOCS) {
|
if (g_debug->config().options() & RECORD_ALLOCS) {
|
||||||
g_debug->record->AddEntry(new MallocEntry(pointer, size));
|
g_debug->record->AddEntry(new MallocEntry(result.getValue<void*>(), size,
|
||||||
|
result.GetStartTimeNS(), result.GetEndTimeNS()));
|
||||||
}
|
}
|
||||||
|
|
||||||
return pointer;
|
return result.getValue<void*>();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void InternalFree(void* pointer) {
|
static TimedResult InternalFree(void* pointer) {
|
||||||
if ((g_debug->config().options() & BACKTRACE) && g_debug->pointer->ShouldDumpAndReset()) {
|
if ((g_debug->config().options() & BACKTRACE) && g_debug->pointer->ShouldDumpAndReset()) {
|
||||||
debug_dump_heap(android::base::StringPrintf(
|
debug_dump_heap(android::base::StringPrintf(
|
||||||
"%s.%d.txt", g_debug->config().backtrace_dump_prefix().c_str(), getpid())
|
"%s.%d.txt", g_debug->config().backtrace_dump_prefix().c_str(), getpid())
|
||||||
|
@ -530,6 +631,7 @@ static void InternalFree(void* pointer) {
|
||||||
PointerData::Remove(pointer);
|
PointerData::Remove(pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TimedResult result;
|
||||||
if (g_debug->config().options() & FREE_TRACK) {
|
if (g_debug->config().options() & FREE_TRACK) {
|
||||||
// Do not add the allocation until we are done modifying the pointer
|
// Do not add the allocation until we are done modifying the pointer
|
||||||
// itself. This avoids a race if a lot of threads are all doing
|
// itself. This avoids a race if a lot of threads are all doing
|
||||||
|
@ -537,15 +639,15 @@ static void InternalFree(void* pointer) {
|
||||||
// pointer from another thread, while still trying to free it in
|
// pointer from another thread, while still trying to free it in
|
||||||
// this function.
|
// this function.
|
||||||
pointer = PointerData::AddFreed(pointer, bytes);
|
pointer = PointerData::AddFreed(pointer, bytes);
|
||||||
if (pointer != nullptr) {
|
if (pointer != nullptr && g_debug->HeaderEnabled()) {
|
||||||
if (g_debug->HeaderEnabled()) {
|
pointer = g_debug->GetHeader(pointer)->orig_pointer;
|
||||||
pointer = g_debug->GetHeader(pointer)->orig_pointer;
|
|
||||||
}
|
|
||||||
g_dispatch->free(pointer);
|
|
||||||
}
|
}
|
||||||
|
result = TCALLVOID(free, pointer);
|
||||||
} else {
|
} else {
|
||||||
g_dispatch->free(free_pointer);
|
result = TCALLVOID(free, free_pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void debug_free(void* pointer) {
|
void debug_free(void* pointer) {
|
||||||
|
@ -558,15 +660,16 @@ void debug_free(void* pointer) {
|
||||||
ScopedDisableDebugCalls disable;
|
ScopedDisableDebugCalls disable;
|
||||||
ScopedBacktraceSignalBlocker blocked;
|
ScopedBacktraceSignalBlocker blocked;
|
||||||
|
|
||||||
if (g_debug->config().options() & RECORD_ALLOCS) {
|
|
||||||
g_debug->record->AddEntry(new FreeEntry(pointer));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!VerifyPointer(pointer, "free")) {
|
if (!VerifyPointer(pointer, "free")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
InternalFree(pointer);
|
TimedResult result = InternalFree(pointer);
|
||||||
|
|
||||||
|
if (g_debug->config().options() & RECORD_ALLOCS) {
|
||||||
|
g_debug->record->AddEntry(
|
||||||
|
new FreeEntry(pointer, result.GetStartTimeNS(), result.GetEndTimeNS()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void* debug_memalign(size_t alignment, size_t bytes) {
|
void* debug_memalign(size_t alignment, size_t bytes) {
|
||||||
|
@ -588,6 +691,7 @@ void* debug_memalign(size_t alignment, size_t bytes) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TimedResult result;
|
||||||
void* pointer;
|
void* pointer;
|
||||||
if (g_debug->HeaderEnabled()) {
|
if (g_debug->HeaderEnabled()) {
|
||||||
// Make the alignment a power of two.
|
// Make the alignment a power of two.
|
||||||
|
@ -610,7 +714,8 @@ void* debug_memalign(size_t alignment, size_t bytes) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
pointer = g_dispatch->malloc(real_size);
|
result = TCALL(malloc, real_size);
|
||||||
|
pointer = result.getValue<void*>();
|
||||||
if (pointer == nullptr) {
|
if (pointer == nullptr) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -620,6 +725,7 @@ void* debug_memalign(size_t alignment, size_t bytes) {
|
||||||
value += (-value % alignment);
|
value += (-value % alignment);
|
||||||
|
|
||||||
Header* header = g_debug->GetHeader(reinterpret_cast<void*>(value));
|
Header* header = g_debug->GetHeader(reinterpret_cast<void*>(value));
|
||||||
|
// Don't need to update `result` here because we only need the timestamps.
|
||||||
pointer = InitHeader(header, pointer, bytes);
|
pointer = InitHeader(header, pointer, bytes);
|
||||||
} else {
|
} else {
|
||||||
size_t real_size = bytes + g_debug->extra_bytes();
|
size_t real_size = bytes + g_debug->extra_bytes();
|
||||||
|
@ -628,7 +734,8 @@ void* debug_memalign(size_t alignment, size_t bytes) {
|
||||||
errno = ENOMEM;
|
errno = ENOMEM;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
pointer = g_dispatch->memalign(alignment, real_size);
|
result = TCALL(memalign, alignment, real_size);
|
||||||
|
pointer = result.getValue<void*>();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pointer != nullptr) {
|
if (pointer != nullptr) {
|
||||||
|
@ -644,7 +751,8 @@ void* debug_memalign(size_t alignment, size_t bytes) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_debug->config().options() & RECORD_ALLOCS) {
|
if (g_debug->config().options() & RECORD_ALLOCS) {
|
||||||
g_debug->record->AddEntry(new MemalignEntry(pointer, bytes, alignment));
|
g_debug->record->AddEntry(new MemalignEntry(pointer, bytes, alignment,
|
||||||
|
result.GetStartTimeNS(), result.GetEndTimeNS()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -662,10 +770,12 @@ void* debug_realloc(void* pointer, size_t bytes) {
|
||||||
ScopedBacktraceSignalBlocker blocked;
|
ScopedBacktraceSignalBlocker blocked;
|
||||||
|
|
||||||
if (pointer == nullptr) {
|
if (pointer == nullptr) {
|
||||||
pointer = InternalMalloc(bytes);
|
TimedResult result = InternalMalloc(bytes);
|
||||||
if (g_debug->config().options() & RECORD_ALLOCS) {
|
if (g_debug->config().options() & RECORD_ALLOCS) {
|
||||||
g_debug->record->AddEntry(new ReallocEntry(pointer, bytes, nullptr));
|
g_debug->record->AddEntry(new ReallocEntry(result.getValue<void*>(), bytes, nullptr,
|
||||||
|
result.GetStartTimeNS(), result.GetEndTimeNS()));
|
||||||
}
|
}
|
||||||
|
pointer = result.getValue<void*>();
|
||||||
return pointer;
|
return pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -674,11 +784,13 @@ void* debug_realloc(void* pointer, size_t bytes) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bytes == 0) {
|
if (bytes == 0) {
|
||||||
|
TimedResult result = InternalFree(pointer);
|
||||||
|
|
||||||
if (g_debug->config().options() & RECORD_ALLOCS) {
|
if (g_debug->config().options() & RECORD_ALLOCS) {
|
||||||
g_debug->record->AddEntry(new ReallocEntry(nullptr, bytes, pointer));
|
g_debug->record->AddEntry(new ReallocEntry(nullptr, bytes, pointer, result.GetStartTimeNS(),
|
||||||
|
result.GetEndTimeNS()));
|
||||||
}
|
}
|
||||||
|
|
||||||
InternalFree(pointer);
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -697,6 +809,7 @@ void* debug_realloc(void* pointer, size_t bytes) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TimedResult result;
|
||||||
void* new_pointer;
|
void* new_pointer;
|
||||||
size_t prev_size;
|
size_t prev_size;
|
||||||
if (g_debug->HeaderEnabled()) {
|
if (g_debug->HeaderEnabled()) {
|
||||||
|
@ -730,7 +843,8 @@ void* debug_realloc(void* pointer, size_t bytes) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate the new size.
|
// Allocate the new size.
|
||||||
new_pointer = InternalMalloc(bytes);
|
result = InternalMalloc(bytes);
|
||||||
|
new_pointer = result.getValue<void*>();
|
||||||
if (new_pointer == nullptr) {
|
if (new_pointer == nullptr) {
|
||||||
errno = ENOMEM;
|
errno = ENOMEM;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -738,14 +852,18 @@ void* debug_realloc(void* pointer, size_t bytes) {
|
||||||
|
|
||||||
prev_size = header->usable_size;
|
prev_size = header->usable_size;
|
||||||
memcpy(new_pointer, pointer, prev_size);
|
memcpy(new_pointer, pointer, prev_size);
|
||||||
InternalFree(pointer);
|
TimedResult free_time = InternalFree(pointer);
|
||||||
|
// `realloc` is split into two steps, update the end time to the finish time
|
||||||
|
// of the second operation.
|
||||||
|
result.SetEndTimeNS(free_time.GetEndTimeNS());
|
||||||
} else {
|
} else {
|
||||||
if (g_debug->TrackPointers()) {
|
if (g_debug->TrackPointers()) {
|
||||||
PointerData::Remove(pointer);
|
PointerData::Remove(pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
prev_size = g_dispatch->malloc_usable_size(pointer);
|
prev_size = g_dispatch->malloc_usable_size(pointer);
|
||||||
new_pointer = g_dispatch->realloc(pointer, real_size);
|
result = TCALL(realloc, pointer, real_size);
|
||||||
|
new_pointer = result.getValue<void*>();
|
||||||
if (new_pointer == nullptr) {
|
if (new_pointer == nullptr) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -767,7 +885,8 @@ void* debug_realloc(void* pointer, size_t bytes) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_debug->config().options() & RECORD_ALLOCS) {
|
if (g_debug->config().options() & RECORD_ALLOCS) {
|
||||||
g_debug->record->AddEntry(new ReallocEntry(new_pointer, bytes, pointer));
|
g_debug->record->AddEntry(new ReallocEntry(new_pointer, bytes, pointer, result.GetStartTimeNS(),
|
||||||
|
result.GetEndTimeNS()));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new_pointer;
|
return new_pointer;
|
||||||
|
@ -807,21 +926,24 @@ void* debug_calloc(size_t nmemb, size_t bytes) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void* pointer;
|
void* pointer;
|
||||||
|
TimedResult result;
|
||||||
if (g_debug->HeaderEnabled()) {
|
if (g_debug->HeaderEnabled()) {
|
||||||
// Need to guarantee the alignment of the header.
|
// Need to guarantee the alignment of the header.
|
||||||
Header* header =
|
result = TCALL(memalign, MINIMUM_ALIGNMENT_BYTES, real_size);
|
||||||
reinterpret_cast<Header*>(g_dispatch->memalign(MINIMUM_ALIGNMENT_BYTES, real_size));
|
Header* header = reinterpret_cast<Header*>(result.getValue<void*>());
|
||||||
if (header == nullptr) {
|
if (header == nullptr) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
memset(header, 0, g_dispatch->malloc_usable_size(header));
|
memset(header, 0, g_dispatch->malloc_usable_size(header));
|
||||||
pointer = InitHeader(header, header, size);
|
pointer = InitHeader(header, header, size);
|
||||||
} else {
|
} else {
|
||||||
pointer = g_dispatch->calloc(1, real_size);
|
result = TCALL(calloc, 1, real_size);
|
||||||
|
pointer = result.getValue<void*>();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_debug->config().options() & RECORD_ALLOCS) {
|
if (g_debug->config().options() & RECORD_ALLOCS) {
|
||||||
g_debug->record->AddEntry(new CallocEntry(pointer, bytes, nmemb));
|
g_debug->record->AddEntry(
|
||||||
|
new CallocEntry(pointer, bytes, nmemb, result.GetStartTimeNS(), result.GetEndTimeNS()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pointer != nullptr && g_debug->TrackPointers()) {
|
if (pointer != nullptr && g_debug->TrackPointers()) {
|
||||||
|
|
|
@ -184,6 +184,23 @@ std::string ShowDiffs(uint8_t* a, uint8_t* b, size_t size) {
|
||||||
return diff;
|
return diff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void VerifyRecords(std::vector<std::string>& expected, std::string& actual) {
|
||||||
|
size_t offset = 0;
|
||||||
|
for (std::string& str : expected) {
|
||||||
|
ASSERT_STREQ(str.c_str(), actual.substr(offset, str.size()).c_str());
|
||||||
|
if (str.find("thread_done") != std::string::npos) {
|
||||||
|
offset = actual.find_first_of("\n", offset) + 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
offset += str.size() + 1;
|
||||||
|
uint64_t st = strtoull(&actual[offset], nullptr, 10);
|
||||||
|
offset = actual.find_first_of(" ", offset) + 1;
|
||||||
|
uint64_t et = strtoull(&actual[offset], nullptr, 10);
|
||||||
|
ASSERT_GT(et, st);
|
||||||
|
offset = actual.find_first_of("\n", offset) + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void VerifyAllocCalls(bool all_options) {
|
void VerifyAllocCalls(bool all_options) {
|
||||||
size_t alloc_size = 1024;
|
size_t alloc_size = 1024;
|
||||||
|
|
||||||
|
@ -2171,61 +2188,61 @@ TEST_F(MallocDebugTest, debug_valloc) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void VerifyRecordAllocs(const std::string& record_filename) {
|
void VerifyRecordAllocs(const std::string& record_filename) {
|
||||||
std::string expected;
|
std::vector<std::string> expected;
|
||||||
|
|
||||||
void* pointer = debug_malloc(10);
|
void* pointer = debug_malloc(10);
|
||||||
ASSERT_TRUE(pointer != nullptr);
|
ASSERT_TRUE(pointer != nullptr);
|
||||||
expected += android::base::StringPrintf("%d: malloc %p 10\n", getpid(), pointer);
|
expected.push_back(android::base::StringPrintf("%d: malloc %p 10", getpid(), pointer));
|
||||||
debug_free(pointer);
|
debug_free(pointer);
|
||||||
expected += android::base::StringPrintf("%d: free %p\n", getpid(), pointer);
|
expected.push_back(android::base::StringPrintf("%d: free %p", getpid(), pointer));
|
||||||
|
|
||||||
pointer = debug_calloc(1, 20);
|
pointer = debug_calloc(1, 20);
|
||||||
ASSERT_TRUE(pointer != nullptr);
|
ASSERT_TRUE(pointer != nullptr);
|
||||||
expected += android::base::StringPrintf("%d: calloc %p 20 1\n", getpid(), pointer);
|
expected.push_back(android::base::StringPrintf("%d: calloc %p 20 1", getpid(), pointer));
|
||||||
debug_free(pointer);
|
debug_free(pointer);
|
||||||
expected += android::base::StringPrintf("%d: free %p\n", getpid(), pointer);
|
expected.push_back(android::base::StringPrintf("%d: free %p", getpid(), pointer));
|
||||||
|
|
||||||
pointer = debug_realloc(nullptr, 30);
|
pointer = debug_realloc(nullptr, 30);
|
||||||
ASSERT_TRUE(pointer != nullptr);
|
ASSERT_TRUE(pointer != nullptr);
|
||||||
expected += android::base::StringPrintf("%d: realloc %p 0x0 30\n", getpid(), pointer);
|
expected.push_back(android::base::StringPrintf("%d: realloc %p 0x0 30", getpid(), pointer));
|
||||||
void* old_pointer = pointer;
|
void* old_pointer = pointer;
|
||||||
pointer = debug_realloc(pointer, 2048);
|
pointer = debug_realloc(pointer, 2048);
|
||||||
ASSERT_TRUE(pointer != nullptr);
|
ASSERT_TRUE(pointer != nullptr);
|
||||||
expected += android::base::StringPrintf("%d: realloc %p %p 2048\n", getpid(),
|
expected.push_back(
|
||||||
pointer, old_pointer);
|
android::base::StringPrintf("%d: realloc %p %p 2048", getpid(), pointer, old_pointer));
|
||||||
debug_realloc(pointer, 0);
|
debug_realloc(pointer, 0);
|
||||||
expected += android::base::StringPrintf("%d: realloc 0x0 %p 0\n", getpid(), pointer);
|
expected.push_back(android::base::StringPrintf("%d: realloc 0x0 %p 0", getpid(), pointer));
|
||||||
|
|
||||||
pointer = debug_memalign(16, 40);
|
pointer = debug_memalign(16, 40);
|
||||||
ASSERT_TRUE(pointer != nullptr);
|
ASSERT_TRUE(pointer != nullptr);
|
||||||
expected += android::base::StringPrintf("%d: memalign %p 16 40\n", getpid(), pointer);
|
expected.push_back(android::base::StringPrintf("%d: memalign %p 16 40", getpid(), pointer));
|
||||||
debug_free(pointer);
|
debug_free(pointer);
|
||||||
expected += android::base::StringPrintf("%d: free %p\n", getpid(), pointer);
|
expected.push_back(android::base::StringPrintf("%d: free %p", getpid(), pointer));
|
||||||
|
|
||||||
pointer = debug_aligned_alloc(32, 64);
|
pointer = debug_aligned_alloc(32, 64);
|
||||||
ASSERT_TRUE(pointer != nullptr);
|
ASSERT_TRUE(pointer != nullptr);
|
||||||
expected += android::base::StringPrintf("%d: memalign %p 32 64\n", getpid(), pointer);
|
expected.push_back(android::base::StringPrintf("%d: memalign %p 32 64", getpid(), pointer));
|
||||||
debug_free(pointer);
|
debug_free(pointer);
|
||||||
expected += android::base::StringPrintf("%d: free %p\n", getpid(), pointer);
|
expected.push_back(android::base::StringPrintf("%d: free %p", getpid(), pointer));
|
||||||
|
|
||||||
ASSERT_EQ(0, debug_posix_memalign(&pointer, 32, 50));
|
ASSERT_EQ(0, debug_posix_memalign(&pointer, 32, 50));
|
||||||
ASSERT_TRUE(pointer != nullptr);
|
ASSERT_TRUE(pointer != nullptr);
|
||||||
expected += android::base::StringPrintf("%d: memalign %p 32 50\n", getpid(), pointer);
|
expected.push_back(android::base::StringPrintf("%d: memalign %p 32 50", getpid(), pointer));
|
||||||
debug_free(pointer);
|
debug_free(pointer);
|
||||||
expected += android::base::StringPrintf("%d: free %p\n", getpid(), pointer);
|
expected.push_back(android::base::StringPrintf("%d: free %p", getpid(), pointer));
|
||||||
|
|
||||||
#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
|
#if defined(HAVE_DEPRECATED_MALLOC_FUNCS)
|
||||||
pointer = debug_pvalloc(60);
|
pointer = debug_pvalloc(60);
|
||||||
ASSERT_TRUE(pointer != nullptr);
|
ASSERT_TRUE(pointer != nullptr);
|
||||||
expected += android::base::StringPrintf("%d: memalign %p 4096 4096\n", getpid(), pointer);
|
expected.push_back(android::base::StringPrintf("%d: memalign %p 4096 4096", getpid(), pointer));
|
||||||
debug_free(pointer);
|
debug_free(pointer);
|
||||||
expected += android::base::StringPrintf("%d: free %p\n", getpid(), pointer);
|
expected.push_back(android::base::StringPrintf("%d: free %p", getpid(), pointer));
|
||||||
|
|
||||||
pointer = debug_valloc(70);
|
pointer = debug_valloc(70);
|
||||||
ASSERT_TRUE(pointer != nullptr);
|
ASSERT_TRUE(pointer != nullptr);
|
||||||
expected += android::base::StringPrintf("%d: memalign %p 4096 70\n", getpid(), pointer);
|
expected.push_back(android::base::StringPrintf("%d: memalign %p 4096 70", getpid(), pointer));
|
||||||
debug_free(pointer);
|
debug_free(pointer);
|
||||||
expected += android::base::StringPrintf("%d: free %p\n", getpid(), pointer);
|
expected.push_back(android::base::StringPrintf("%d: free %p", getpid(), pointer));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Dump all of the data accumulated so far.
|
// Dump all of the data accumulated so far.
|
||||||
|
@ -2235,7 +2252,7 @@ void VerifyRecordAllocs(const std::string& record_filename) {
|
||||||
std::string actual;
|
std::string actual;
|
||||||
ASSERT_TRUE(android::base::ReadFileToString(record_filename, &actual));
|
ASSERT_TRUE(android::base::ReadFileToString(record_filename, &actual));
|
||||||
|
|
||||||
ASSERT_STREQ(expected.c_str(), actual.c_str());
|
VerifyRecords(expected, actual);
|
||||||
|
|
||||||
ASSERT_STREQ("", getFakeLogBuf().c_str());
|
ASSERT_STREQ("", getFakeLogBuf().c_str());
|
||||||
ASSERT_STREQ("", getFakeLogPrint().c_str());
|
ASSERT_STREQ("", getFakeLogPrint().c_str());
|
||||||
|
@ -2256,23 +2273,23 @@ TEST_F(MallocDebugTest, record_allocs_with_header) {
|
||||||
TEST_F(MallocDebugTest, record_allocs_max) {
|
TEST_F(MallocDebugTest, record_allocs_max) {
|
||||||
InitRecordAllocs("record_allocs=5");
|
InitRecordAllocs("record_allocs=5");
|
||||||
|
|
||||||
std::string expected;
|
std::vector<std::string> expected;
|
||||||
|
|
||||||
void* pointer = debug_malloc(10);
|
void* pointer = debug_malloc(10);
|
||||||
ASSERT_TRUE(pointer != nullptr);
|
ASSERT_TRUE(pointer != nullptr);
|
||||||
expected += android::base::StringPrintf("%d: malloc %p 10\n", getpid(), pointer);
|
expected.push_back(android::base::StringPrintf("%d: malloc %p 10", getpid(), pointer));
|
||||||
debug_free(pointer);
|
debug_free(pointer);
|
||||||
expected += android::base::StringPrintf("%d: free %p\n", getpid(), pointer);
|
expected.push_back(android::base::StringPrintf("%d: free %p", getpid(), pointer));
|
||||||
|
|
||||||
pointer = debug_malloc(20);
|
pointer = debug_malloc(20);
|
||||||
ASSERT_TRUE(pointer != nullptr);
|
ASSERT_TRUE(pointer != nullptr);
|
||||||
expected += android::base::StringPrintf("%d: malloc %p 20\n", getpid(), pointer);
|
expected.push_back(android::base::StringPrintf("%d: malloc %p 20", getpid(), pointer));
|
||||||
debug_free(pointer);
|
debug_free(pointer);
|
||||||
expected += android::base::StringPrintf("%d: free %p\n", getpid(), pointer);
|
expected.push_back(android::base::StringPrintf("%d: free %p", getpid(), pointer));
|
||||||
|
|
||||||
pointer = debug_malloc(1024);
|
pointer = debug_malloc(1024);
|
||||||
ASSERT_TRUE(pointer != nullptr);
|
ASSERT_TRUE(pointer != nullptr);
|
||||||
expected += android::base::StringPrintf("%d: malloc %p 1024\n", getpid(), pointer);
|
expected.push_back(android::base::StringPrintf("%d: malloc %p 1024", getpid(), pointer));
|
||||||
debug_free(pointer);
|
debug_free(pointer);
|
||||||
|
|
||||||
// Dump all of the data accumulated so far.
|
// Dump all of the data accumulated so far.
|
||||||
|
@ -2282,7 +2299,7 @@ TEST_F(MallocDebugTest, record_allocs_max) {
|
||||||
std::string actual;
|
std::string actual;
|
||||||
ASSERT_TRUE(android::base::ReadFileToString(record_filename, &actual));
|
ASSERT_TRUE(android::base::ReadFileToString(record_filename, &actual));
|
||||||
|
|
||||||
ASSERT_STREQ(expected.c_str(), actual.c_str());
|
VerifyRecords(expected, actual);
|
||||||
|
|
||||||
ASSERT_STREQ("", getFakeLogBuf().c_str());
|
ASSERT_STREQ("", getFakeLogBuf().c_str());
|
||||||
ASSERT_STREQ(
|
ASSERT_STREQ(
|
||||||
|
@ -2303,9 +2320,10 @@ TEST_F(MallocDebugTest, record_allocs_thread_done) {
|
||||||
});
|
});
|
||||||
thread.join();
|
thread.join();
|
||||||
|
|
||||||
std::string expected = android::base::StringPrintf("%d: malloc %p 100\n", tid, pointer);
|
std::vector<std::string> expected;
|
||||||
expected += android::base::StringPrintf("%d: free %p\n", tid, pointer);
|
expected.push_back(android::base::StringPrintf("%d: malloc %p 100", tid, pointer));
|
||||||
expected += android::base::StringPrintf("%d: thread_done 0x0\n", tid);
|
expected.push_back(android::base::StringPrintf("%d: free %p", tid, pointer));
|
||||||
|
expected.push_back(android::base::StringPrintf("%d: thread_done 0x0", tid));
|
||||||
|
|
||||||
// Dump all of the data accumulated so far.
|
// Dump all of the data accumulated so far.
|
||||||
ASSERT_TRUE(kill(getpid(), SIGRTMAX - 18) == 0);
|
ASSERT_TRUE(kill(getpid(), SIGRTMAX - 18) == 0);
|
||||||
|
@ -2314,7 +2332,7 @@ TEST_F(MallocDebugTest, record_allocs_thread_done) {
|
||||||
std::string actual;
|
std::string actual;
|
||||||
ASSERT_TRUE(android::base::ReadFileToString(record_filename, &actual));
|
ASSERT_TRUE(android::base::ReadFileToString(record_filename, &actual));
|
||||||
|
|
||||||
ASSERT_STREQ(expected.c_str(), actual.c_str());
|
VerifyRecords(expected, actual);
|
||||||
|
|
||||||
ASSERT_STREQ("", getFakeLogBuf().c_str());
|
ASSERT_STREQ("", getFakeLogBuf().c_str());
|
||||||
ASSERT_STREQ("", getFakeLogPrint().c_str());
|
ASSERT_STREQ("", getFakeLogPrint().c_str());
|
||||||
|
@ -2329,13 +2347,13 @@ TEST_F(MallocDebugTest, record_allocs_file_name_fail) {
|
||||||
|
|
||||||
ASSERT_EQ(0, symlink("/data/local/tmp/does_not_exist", record_filename.c_str()));
|
ASSERT_EQ(0, symlink("/data/local/tmp/does_not_exist", record_filename.c_str()));
|
||||||
|
|
||||||
std::string expected;
|
std::vector<std::string> expected;
|
||||||
|
|
||||||
void* pointer = debug_malloc(10);
|
void* pointer = debug_malloc(10);
|
||||||
ASSERT_TRUE(pointer != nullptr);
|
ASSERT_TRUE(pointer != nullptr);
|
||||||
expected += android::base::StringPrintf("%d: malloc %p 10\n", getpid(), pointer);
|
expected.push_back(android::base::StringPrintf("%d: malloc %p 10", getpid(), pointer));
|
||||||
debug_free(pointer);
|
debug_free(pointer);
|
||||||
expected += android::base::StringPrintf("%d: free %p\n", getpid(), pointer);
|
expected.push_back(android::base::StringPrintf("%d: free %p", getpid(), pointer));
|
||||||
|
|
||||||
// Dump all of the data accumulated so far.
|
// Dump all of the data accumulated so far.
|
||||||
ASSERT_TRUE(kill(getpid(), SIGRTMAX - 18) == 0);
|
ASSERT_TRUE(kill(getpid(), SIGRTMAX - 18) == 0);
|
||||||
|
@ -2351,7 +2369,8 @@ TEST_F(MallocDebugTest, record_allocs_file_name_fail) {
|
||||||
ASSERT_TRUE(kill(getpid(), SIGRTMAX - 18) == 0);
|
ASSERT_TRUE(kill(getpid(), SIGRTMAX - 18) == 0);
|
||||||
|
|
||||||
ASSERT_TRUE(android::base::ReadFileToString(record_filename, &actual));
|
ASSERT_TRUE(android::base::ReadFileToString(record_filename, &actual));
|
||||||
ASSERT_STREQ(expected.c_str(), actual.c_str());
|
|
||||||
|
VerifyRecords(expected, actual);
|
||||||
|
|
||||||
ASSERT_STREQ("", getFakeLogBuf().c_str());
|
ASSERT_STREQ("", getFakeLogBuf().c_str());
|
||||||
std::string expected_log = android::base::StringPrintf(
|
std::string expected_log = android::base::StringPrintf(
|
||||||
|
@ -2375,13 +2394,13 @@ TEST_F(MallocDebugTest, record_allocs_no_entries_to_write) {
|
||||||
TEST_F(MallocDebugTest, record_allocs_write_entries_does_not_allocate) {
|
TEST_F(MallocDebugTest, record_allocs_write_entries_does_not_allocate) {
|
||||||
InitRecordAllocs("record_allocs=5");
|
InitRecordAllocs("record_allocs=5");
|
||||||
|
|
||||||
std::string expected;
|
std::vector<std::string> expected;
|
||||||
|
|
||||||
void* pointer = debug_malloc(10);
|
void* pointer = debug_malloc(10);
|
||||||
ASSERT_TRUE(pointer != nullptr);
|
ASSERT_TRUE(pointer != nullptr);
|
||||||
expected += android::base::StringPrintf("%d: malloc %p 10\n", getpid(), pointer);
|
expected.push_back(android::base::StringPrintf("%d: malloc %p 10", getpid(), pointer));
|
||||||
debug_free(pointer);
|
debug_free(pointer);
|
||||||
expected += android::base::StringPrintf("%d: free %p\n", getpid(), pointer);
|
expected.push_back(android::base::StringPrintf("%d: free %p", getpid(), pointer));
|
||||||
|
|
||||||
malloc_disable();
|
malloc_disable();
|
||||||
kill(getpid(), SIGRTMAX - 18);
|
kill(getpid(), SIGRTMAX - 18);
|
||||||
|
@ -2389,7 +2408,8 @@ TEST_F(MallocDebugTest, record_allocs_write_entries_does_not_allocate) {
|
||||||
|
|
||||||
std::string actual;
|
std::string actual;
|
||||||
ASSERT_TRUE(android::base::ReadFileToString(record_filename, &actual));
|
ASSERT_TRUE(android::base::ReadFileToString(record_filename, &actual));
|
||||||
ASSERT_STREQ(expected.c_str(), actual.c_str());
|
|
||||||
|
VerifyRecords(expected, actual);
|
||||||
|
|
||||||
ASSERT_STREQ("", getFakeLogBuf().c_str());
|
ASSERT_STREQ("", getFakeLogBuf().c_str());
|
||||||
ASSERT_STREQ("", getFakeLogPrint().c_str());
|
ASSERT_STREQ("", getFakeLogPrint().c_str());
|
||||||
|
|
Loading…
Reference in a new issue