Skip to content

Commit

Permalink
Add simple allocation tracer on Linux.
Browse files Browse the repository at this point in the history
  • Loading branch information
john-preston committed May 14, 2021
1 parent ce5e581 commit 8e231d2
Show file tree
Hide file tree
Showing 3 changed files with 203 additions and 1 deletion.
13 changes: 12 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ PRIVATE
base/platform/linux/base_last_input_linux.h
base/platform/linux/base_layout_switch_linux.cpp
base/platform/linux/base_layout_switch_linux.h
base/platform/linux/base_linux_allocation_tracer.cpp
base/platform/linux/base_linux_allocation_tracer.h
base/platform/linux/base_linux_dbus_utilities.cpp
base/platform/linux/base_linux_dbus_utilities.h
base/platform/linux/base_linux_glibmm_helper.h
Expand Down Expand Up @@ -262,7 +264,16 @@ if (LINUX)
endif()
endif()

target_compile_definitions(lib_base PRIVATE G_LOG_DOMAIN="lib_base")
target_compile_definitions(lib_base
PRIVATE
G_LOG_DOMAIN="lib_base"
)
if (DESKTOP_APP_USE_ALLOCATION_TRACER)
target_compile_definitions(lib_base
PRIVATE
DESKTOP_APP_USE_ALLOCATION_TRACER
)
endif()

#target_precompile_headers(lib_base_crash_report_writer REUSE_FROM lib_base)
target_precompile_headers(lib_base_crash_report_writer PRIVATE ${src_loc}/base/base_pch.h)
Expand Down
176 changes: 176 additions & 0 deletions base/platform/linux/base_linux_allocation_tracer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "base/platform/linux/base_linux_allocation_tracer.h"

#include "base/debug_log.h"

#include <mutex>
#include <stdio.h>
#include <unistd.h>

void SetMallocLogger(void (*logger)(size_t, void *));
void SetVallocLogger(void (*logger)(size_t, void *));
void SetPVallocLogger(void (*logger)(size_t, void *));
void SetReallocLogger(void (*logger)(void *, size_t, void *));
void SetFreeLogger(void (*logger)(void *));
void SetMemAlignLogger(void (*logger)(size_t, size_t, void *));
void SetAlignedAllocLogger(void (*logger)(size_t, size_t, void *));
void SetPosixMemAlignLogger(void (*logger)(size_t, size_t, void *));
void SetCallocLogger(void (*logger)(size_t, size_t, void *));

namespace base::Platform {
namespace {

#ifdef DESKTOP_APP_USE_ALLOCATION_TRACER

constexpr auto kBufferSize = 1024 * 1024;

char *Buffer/* = nullptr*/;
FILE *File/* = 0*/;
char *Data/* = nullptr*/;
std::mutex Mutex;

void WriteBlock() {
if (Data > Buffer) {
fwrite(Buffer, Data - Buffer, 1, File);
fflush(File);
fdatasync(fileno(File));
Data = Buffer;
}
}

template <size_t Size>
void AppendEntry(char (&bytes)[Size]) {
std::unique_lock<std::mutex> lock(Mutex);
if (!File) {
return;
} else if (Data + Size > Buffer + kBufferSize) {
WriteBlock();
}
*reinterpret_cast<std::uint32_t*>(bytes + 1) = uint32_t(time(nullptr));
memcpy(Data, bytes, Size);
Data += Size;
}

void MallocLogger(size_t size, void *result) {
char entry[5 + sizeof(std::uint64_t) * 2];
entry[0] = 1;
*reinterpret_cast<std::uint64_t*>(entry + 5)
= static_cast<std::uint64_t>(size);
*reinterpret_cast<std::uint64_t*>(entry + 5 + sizeof(std::uint64_t))
= reinterpret_cast<std::uint64_t>(result);
AppendEntry(entry);
}

void VallocLogger(size_t size, void *result) {
MallocLogger(size, result);
}

void PVallocLogger(size_t size, void *result) {
MallocLogger(size, result);
}

void CallocLogger(size_t num, size_t size, void *result) {
MallocLogger(num * size, result);
}

void ReallocLogger(void *ptr, size_t size, void *result) {
if (!ptr) {
return MallocLogger(size, result);
}
char entry[5 + sizeof(std::uint64_t) * 3];
entry[0] = 2;
*reinterpret_cast<std::uint64_t*>(entry + 5)
= reinterpret_cast<std::uint64_t>(ptr);
*reinterpret_cast<std::uint64_t*>(entry + 5 + sizeof(std::uint64_t))
= static_cast<std::uint64_t>(size);
*reinterpret_cast<std::uint64_t*>(entry + 5 + sizeof(std::uint64_t) * 2)
= reinterpret_cast<std::uint64_t>(result);
AppendEntry(entry);
}

void MemAlignLogger(size_t alignment, size_t size, void *result) {
MallocLogger(size, result);
}

void AlignedAllocLogger(size_t alignment, size_t size, void *result) {
MallocLogger(size, result);
}

void PosixMemAlignLogger(size_t alignment, size_t size, void *result) {
MallocLogger(size, result);
}

void FreeLogger(void *ptr) {
if (ptr) {
char entry[5 + sizeof(std::uint64_t)];
entry[0] = 3;
*reinterpret_cast<std::uint64_t*>(entry + 5)
= reinterpret_cast<std::uint64_t>(ptr);
AppendEntry(entry);
}
}

void InstallLoggers() {
SetMallocLogger(MallocLogger);
SetVallocLogger(VallocLogger);
SetPVallocLogger(PVallocLogger);
SetCallocLogger(CallocLogger);
SetReallocLogger(ReallocLogger);
SetMemAlignLogger(MemAlignLogger);
SetAlignedAllocLogger(AlignedAllocLogger);
SetPosixMemAlignLogger(PosixMemAlignLogger);
SetFreeLogger(FreeLogger);
}

void RemoveLoggers() {
SetMallocLogger(nullptr);
SetVallocLogger(nullptr);
SetPVallocLogger(nullptr);
SetCallocLogger(nullptr);
SetReallocLogger(nullptr);
SetMemAlignLogger(nullptr);
SetAlignedAllocLogger(nullptr);
SetPosixMemAlignLogger(nullptr);
SetFreeLogger(nullptr);
}

#endif // DESKTOP_APP_USE_ALLOCATION_TRACER

} // namespace

void SetAllocationTracerPath(const QString &path) {
#ifdef DESKTOP_APP_USE_ALLOCATION_TRACER
Expects(!Buffer);

Data = Buffer = new char[kBufferSize];
if (!Buffer) {
return;
}
File = fopen(path.toStdString().c_str(), "wb");
if (!File) {
return;
}
InstallLoggers();
#endif // DESKTOP_APP_USE_ALLOCATION_TRACER
}

void FinishAllocationTracer() {
#ifdef DESKTOP_APP_USE_ALLOCATION_TRACER
if (File) {
RemoveLoggers();

std::unique_lock<std::mutex> lock(Mutex);
WriteBlock();
fclose(File);
File = nullptr;
}
#endif // DESKTOP_APP_USE_ALLOCATION_TRACER
}

} // namespace base::Platform
15 changes: 15 additions & 0 deletions base/platform/linux/base_linux_allocation_tracer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once

namespace base::Platform {

void SetAllocationTracerPath(const QString &path);
void FinishAllocationTracer();

} // namespace base::Platform

0 comments on commit 8e231d2

Please sign in to comment.