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