Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions src/lib/symbol_overrides.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@
#include <ctime>
#include <dlfcn.h>
#include <malloc.h>
#include <sys/ipc.h>
#include <sys/mman.h>
#include <sys/shm.h>

#if defined(__GNUC__) && !defined(__clang__)
# define NOEXCEPT noexcept
Expand All @@ -35,6 +37,14 @@ extern "C" {
// Declaration of reallocarray is only available starting from glibc 2.28
DDPROF_WEAK void *reallocarray(void *ptr, size_t nmemb, size_t nmenb) NOEXCEPT;
DDPROF_WEAK void *pvalloc(size_t size) NOEXCEPT;
DDPROF_WEAK void *mremap(void *old_address, size_t old_size, size_t new_size,
int flags, ...) NOEXCEPT;
DDPROF_WEAK void *shmat(int shmid, const void *shmaddr, int shmflg) NOEXCEPT;
DDPROF_WEAK int shmdt(const void *shmaddr) NOEXCEPT;
// brk()/sbrk() are not instrumented:
// - They grow/shrink the program break, not individual allocations
// - Would double-count if malloc uses them internally
// - Tracking would require maintaining state of what's actually allocated
DDPROF_WEAK int __libc_allocate_rtsig(int high) NOEXCEPT;
// NOLINTEND

Expand Down Expand Up @@ -857,6 +867,57 @@ struct Munmap_Hook : HookBase {
}
};

struct MremapHook : HookBase {
static constexpr auto name = "mremap";
using FuncType = decltype(&::mremap);
static inline FuncType ref{};

static void *hook(void *old_address, size_t old_size, size_t new_size,
int flags) noexcept {
AllocTrackerHelperMmap helper;
if (likely(old_address) && helper) {
ddprof::AllocationTracker::track_deallocation_s(
reinterpret_cast<uintptr_t>(old_address), *helper.tl_state(), true);
}
auto *new_ptr = ref(old_address, old_size, new_size, flags);

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

todo: this does not have the guard

if (likely(new_size && new_ptr != MAP_FAILED)) {
helper.track(new_ptr, new_size);
}
return new_ptr;
}
};

struct ShmatHook : HookBase {
static constexpr auto name = "shmat";
using FuncType = decltype(&::shmat);
static inline FuncType ref{};

static void *hook(int shmid, const void *shmaddr, int shmflg) noexcept {
void *ptr = ref(shmid, shmaddr, shmflg);
if (ptr != reinterpret_cast<void *>(-1)) {
AllocTrackerHelperMmap helper;
// Query the segment size via shmctl
struct shmid_ds buf;
if (shmctl(shmid, IPC_STAT, &buf) == 0) {
helper.track(ptr, buf.shm_segsz);
}
}
return ptr;
}
};

struct ShmdtHook : HookBase {
static constexpr auto name = "shmdt";
using FuncType = decltype(&::shmdt);
static inline FuncType ref{};

static int hook(const void *shmaddr) noexcept {
DeallocTrackerHelperMmap helper;
helper.track(const_cast<void *>(shmaddr));
return ref(shmaddr);
}
};

template <typename T> void register_hook() {
g_symbol_overrides->register_override(T::name,
reinterpret_cast<uintptr_t>(&T::hook),
Expand Down Expand Up @@ -922,6 +983,9 @@ void register_hooks() {
register_hook<MunmapHook>();
register_hook<Mmap_Hook>();
register_hook<Munmap_Hook>();
register_hook<MremapHook>();
register_hook<ShmatHook>();
register_hook<ShmdtHook>();

register_hook<MallocxHook>();
register_hook<RallocxHook>();
Expand Down
35 changes: 34 additions & 1 deletion test/allocation_tracker-ut.cc
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,9 @@ DDPROF_WEAK void sdallocx(void *ptr, size_t size, int flags);
}
#endif
#include <malloc.h>
#include <sys/ipc.h>
#include <sys/mman.h>
#include <sys/shm.h>
#include <unistd.h>

#if defined(__GNUC__) && !defined(__clang__)
Expand All @@ -61,6 +63,10 @@ DDPROF_WEAK void *pvalloc(size_t size) NOEXCEPT;
DDPROF_WEAK void *__mmap(void *addr, size_t length, int prot, int flags, int fd,
off_t offset);
DDPROF_WEAK int __munmap(void *addr, size_t length);
DDPROF_WEAK void *mremap(void *old_address, size_t old_size, size_t new_size,
int flags, ...) NOEXCEPT;
DDPROF_WEAK void *shmat(int shmid, const void *shmaddr, int shmflg) NOEXCEPT;
DDPROF_WEAK int shmdt(const void *shmaddr) NOEXCEPT;
}

namespace ddprof {
Expand Down Expand Up @@ -505,7 +511,34 @@ DDPROF_NOINLINE void test_allocation_functions(RingBuffer &ring_buffer) {
SCOPED_TRACE("__mmap/__munmap");
checker.test_alloc(mmap_wrapper(&::__mmap), &::__munmap);
}

if (mremap) {
SCOPED_TRACE("mremap");
checker.test_realloc(
mmap_wrapper(&::mmap),
[](void *ptr, size_t new_sz) {
auto old_sz = alloc_size;
auto *new_ptr = ::mremap(ptr, old_sz, new_sz, MREMAP_MAYMOVE);
return std::make_pair(new_ptr, new_sz);
},
[](void *ptr, size_t sz) { ::munmap(ptr, sz); });
}
if (shmat && shmdt) {
SCOPED_TRACE("shmat/shmdt");
// Create a System V shared memory segment
int shmid = shmget(IPC_PRIVATE, alloc_size, IPC_CREAT | 0600);
if (shmid != -1) {
checker.empty_ring_buffer();
void *ptr = ::shmat(shmid, nullptr, 0);
if (ptr != reinterpret_cast<void *>(-1)) {
checker.check_alloc(ptr, alloc_size);
checker.check_empty();
::shmdt(ptr);
checker.check_dealloc(ptr);
checker.check_empty();
}
shmctl(shmid, IPC_RMID, nullptr);
}
}
static constexpr size_t big_align = alignof(std::max_align_t) * 2;
static constexpr size_t array_size = 16;
static_assert((alloc_size / array_size) % big_align == 0);
Expand Down