166 lines · cpp
1//===-- memprof_malloc_linux.cpp -----------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file is a part of MemProfiler, a memory profiler.10//11// Linux-specific malloc interception.12// We simply define functions like malloc, free, realloc, etc.13// They will replace the corresponding libc functions automagically.14//===----------------------------------------------------------------------===//15 16#include "sanitizer_common/sanitizer_platform.h"17#if !SANITIZER_LINUX18#error Unsupported OS19#endif20 21#include "memprof_allocator.h"22#include "memprof_interceptors.h"23#include "memprof_internal.h"24#include "memprof_stack.h"25#include "sanitizer_common/sanitizer_allocator_checks.h"26#include "sanitizer_common/sanitizer_allocator_dlsym.h"27#include "sanitizer_common/sanitizer_errno.h"28#include "sanitizer_common/sanitizer_tls_get_addr.h"29 30// ---------------------- Replacement functions ---------------- {{{131using namespace __memprof;32 33struct DlsymAlloc : public DlSymAllocator<DlsymAlloc> {34 static bool UseImpl() { return memprof_init_is_running; }35};36 37INTERCEPTOR(void, free, void *ptr) {38 if (DlsymAlloc::PointerIsMine(ptr))39 return DlsymAlloc::Free(ptr);40 GET_STACK_TRACE_FREE;41 memprof_free(ptr, &stack, FROM_MALLOC);42}43 44#if SANITIZER_INTERCEPT_CFREE45INTERCEPTOR(void, cfree, void *ptr) {46 if (DlsymAlloc::PointerIsMine(ptr))47 return DlsymAlloc::Free(ptr);48 GET_STACK_TRACE_FREE;49 memprof_free(ptr, &stack, FROM_MALLOC);50}51#endif // SANITIZER_INTERCEPT_CFREE52 53#if SANITIZER_INTERCEPT_FREE_SIZED54INTERCEPTOR(void, free_sized, void *ptr, uptr size) {55 if (DlsymAlloc::PointerIsMine(ptr))56 return DlsymAlloc::Free(ptr);57 GET_STACK_TRACE_FREE;58 memprof_delete(ptr, size, 0, &stack, FROM_MALLOC);59}60#endif // SANITIZER_INTERCEPT_FREE_SIZED61 62#if SANITIZER_INTERCEPT_FREE_ALIGNED_SIZED63INTERCEPTOR(void, free_aligned_sized, void *ptr, uptr alignment, uptr size) {64 if (DlsymAlloc::PointerIsMine(ptr))65 return DlsymAlloc::Free(ptr);66 GET_STACK_TRACE_FREE;67 memprof_delete(ptr, size, alignment, &stack, FROM_MALLOC);68}69#endif // SANITIZER_INTERCEPT_FREE_ALIGNED_SIZED70 71INTERCEPTOR(void *, malloc, uptr size) {72 if (DlsymAlloc::Use())73 return DlsymAlloc::Allocate(size);74 ENSURE_MEMPROF_INITED();75 GET_STACK_TRACE_MALLOC;76 return memprof_malloc(size, &stack);77}78 79INTERCEPTOR(void *, calloc, uptr nmemb, uptr size) {80 if (DlsymAlloc::Use())81 return DlsymAlloc::Callocate(nmemb, size);82 ENSURE_MEMPROF_INITED();83 GET_STACK_TRACE_MALLOC;84 return memprof_calloc(nmemb, size, &stack);85}86 87INTERCEPTOR(void *, realloc, void *ptr, uptr size) {88 if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(ptr))89 return DlsymAlloc::Realloc(ptr, size);90 ENSURE_MEMPROF_INITED();91 GET_STACK_TRACE_MALLOC;92 return memprof_realloc(ptr, size, &stack);93}94 95#if SANITIZER_INTERCEPT_REALLOCARRAY96INTERCEPTOR(void *, reallocarray, void *ptr, uptr nmemb, uptr size) {97 ENSURE_MEMPROF_INITED();98 GET_STACK_TRACE_MALLOC;99 return memprof_reallocarray(ptr, nmemb, size, &stack);100}101#endif // SANITIZER_INTERCEPT_REALLOCARRAY102 103#if SANITIZER_INTERCEPT_MEMALIGN104INTERCEPTOR(void *, memalign, uptr boundary, uptr size) {105 GET_STACK_TRACE_MALLOC;106 return memprof_memalign(boundary, size, &stack, FROM_MALLOC);107}108 109INTERCEPTOR(void *, __libc_memalign, uptr boundary, uptr size) {110 GET_STACK_TRACE_MALLOC;111 return memprof_memalign(boundary, size, &stack, FROM_MALLOC);112}113#endif // SANITIZER_INTERCEPT_MEMALIGN114 115#if SANITIZER_INTERCEPT_ALIGNED_ALLOC116INTERCEPTOR(void *, aligned_alloc, uptr boundary, uptr size) {117 GET_STACK_TRACE_MALLOC;118 return memprof_aligned_alloc(boundary, size, &stack);119}120#endif // SANITIZER_INTERCEPT_ALIGNED_ALLOC121 122INTERCEPTOR(uptr, malloc_usable_size, void *ptr) {123 return memprof_malloc_usable_size(ptr);124}125 126#if SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO127// We avoid including malloc.h for portability reasons.128// man mallinfo says the fields are "long", but the implementation uses int.129// It doesn't matter much -- we just need to make sure that the libc's mallinfo130// is not called.131struct fake_mallinfo {132 int x[10];133};134 135INTERCEPTOR(struct fake_mallinfo, mallinfo, void) {136 struct fake_mallinfo res;137 REAL(memset)(&res, 0, sizeof(res));138 return res;139}140 141INTERCEPTOR(int, mallopt, int cmd, int value) { return 0; }142#endif // SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO143 144INTERCEPTOR(int, posix_memalign, void **memptr, uptr alignment, uptr size) {145 GET_STACK_TRACE_MALLOC;146 return memprof_posix_memalign(memptr, alignment, size, &stack);147}148 149INTERCEPTOR(void *, valloc, uptr size) {150 GET_STACK_TRACE_MALLOC;151 return memprof_valloc(size, &stack);152}153 154#if SANITIZER_INTERCEPT_PVALLOC155INTERCEPTOR(void *, pvalloc, uptr size) {156 GET_STACK_TRACE_MALLOC;157 return memprof_pvalloc(size, &stack);158}159#endif // SANITIZER_INTERCEPT_PVALLOC160 161INTERCEPTOR(void, malloc_stats, void) { __memprof_print_accumulated_stats(); }162 163namespace __memprof {164void ReplaceSystemMalloc() {}165} // namespace __memprof166