13d4bba30STeresa Johnson //===-- memprof_malloc_linux.cpp -----------------------------------------===//
23d4bba30STeresa Johnson //
33d4bba30STeresa Johnson // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
43d4bba30STeresa Johnson // See https://llvm.org/LICENSE.txt for license information.
53d4bba30STeresa Johnson // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63d4bba30STeresa Johnson //
73d4bba30STeresa Johnson //===----------------------------------------------------------------------===//
83d4bba30STeresa Johnson //
93d4bba30STeresa Johnson // This file is a part of MemProfiler, a memory profiler.
103d4bba30STeresa Johnson //
113d4bba30STeresa Johnson // Linux-specific malloc interception.
123d4bba30STeresa Johnson // We simply define functions like malloc, free, realloc, etc.
133d4bba30STeresa Johnson // They will replace the corresponding libc functions automagically.
143d4bba30STeresa Johnson //===----------------------------------------------------------------------===//
153d4bba30STeresa Johnson
163d4bba30STeresa Johnson #include "sanitizer_common/sanitizer_platform.h"
173d4bba30STeresa Johnson #if !SANITIZER_LINUX
183d4bba30STeresa Johnson #error Unsupported OS
193d4bba30STeresa Johnson #endif
203d4bba30STeresa Johnson
213d4bba30STeresa Johnson #include "memprof_allocator.h"
223d4bba30STeresa Johnson #include "memprof_interceptors.h"
233d4bba30STeresa Johnson #include "memprof_internal.h"
243d4bba30STeresa Johnson #include "memprof_stack.h"
253d4bba30STeresa Johnson #include "sanitizer_common/sanitizer_allocator_checks.h"
26*cb0e14ceSVitaly Buka #include "sanitizer_common/sanitizer_allocator_dlsym.h"
273d4bba30STeresa Johnson #include "sanitizer_common/sanitizer_errno.h"
283d4bba30STeresa Johnson #include "sanitizer_common/sanitizer_tls_get_addr.h"
293d4bba30STeresa Johnson
303d4bba30STeresa Johnson // ---------------------- Replacement functions ---------------- {{{1
313d4bba30STeresa Johnson using namespace __memprof;
323d4bba30STeresa Johnson
33*cb0e14ceSVitaly Buka struct DlsymAlloc : public DlSymAllocator<DlsymAlloc> {
UseImplDlsymAlloc34*cb0e14ceSVitaly Buka static bool UseImpl() { return memprof_init_is_running; }
35*cb0e14ceSVitaly Buka };
363d4bba30STeresa Johnson
INTERCEPTOR(void,free,void * ptr)373d4bba30STeresa Johnson INTERCEPTOR(void, free, void *ptr) {
38*cb0e14ceSVitaly Buka if (DlsymAlloc::PointerIsMine(ptr))
39*cb0e14ceSVitaly Buka return DlsymAlloc::Free(ptr);
40651797f4SVitaly Buka GET_STACK_TRACE_FREE;
413d4bba30STeresa Johnson memprof_free(ptr, &stack, FROM_MALLOC);
423d4bba30STeresa Johnson }
433d4bba30STeresa Johnson
443d4bba30STeresa Johnson #if SANITIZER_INTERCEPT_CFREE
INTERCEPTOR(void,cfree,void * ptr)453d4bba30STeresa Johnson INTERCEPTOR(void, cfree, void *ptr) {
46*cb0e14ceSVitaly Buka if (DlsymAlloc::PointerIsMine(ptr))
47*cb0e14ceSVitaly Buka return DlsymAlloc::Free(ptr);
48651797f4SVitaly Buka GET_STACK_TRACE_FREE;
493d4bba30STeresa Johnson memprof_free(ptr, &stack, FROM_MALLOC);
503d4bba30STeresa Johnson }
513d4bba30STeresa Johnson #endif // SANITIZER_INTERCEPT_CFREE
523d4bba30STeresa Johnson
INTERCEPTOR(void *,malloc,uptr size)533d4bba30STeresa Johnson INTERCEPTOR(void *, malloc, uptr size) {
54*cb0e14ceSVitaly Buka if (DlsymAlloc::Use())
55*cb0e14ceSVitaly Buka return DlsymAlloc::Allocate(size);
563d4bba30STeresa Johnson ENSURE_MEMPROF_INITED();
573d4bba30STeresa Johnson GET_STACK_TRACE_MALLOC;
583d4bba30STeresa Johnson return memprof_malloc(size, &stack);
593d4bba30STeresa Johnson }
603d4bba30STeresa Johnson
INTERCEPTOR(void *,calloc,uptr nmemb,uptr size)613d4bba30STeresa Johnson INTERCEPTOR(void *, calloc, uptr nmemb, uptr size) {
62*cb0e14ceSVitaly Buka if (DlsymAlloc::Use())
63*cb0e14ceSVitaly Buka return DlsymAlloc::Callocate(nmemb, size);
643d4bba30STeresa Johnson ENSURE_MEMPROF_INITED();
653d4bba30STeresa Johnson GET_STACK_TRACE_MALLOC;
663d4bba30STeresa Johnson return memprof_calloc(nmemb, size, &stack);
673d4bba30STeresa Johnson }
683d4bba30STeresa Johnson
INTERCEPTOR(void *,realloc,void * ptr,uptr size)693d4bba30STeresa Johnson INTERCEPTOR(void *, realloc, void *ptr, uptr size) {
70*cb0e14ceSVitaly Buka if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(ptr))
71*cb0e14ceSVitaly Buka return DlsymAlloc::Realloc(ptr, size);
723d4bba30STeresa Johnson ENSURE_MEMPROF_INITED();
733d4bba30STeresa Johnson GET_STACK_TRACE_MALLOC;
743d4bba30STeresa Johnson return memprof_realloc(ptr, size, &stack);
753d4bba30STeresa Johnson }
763d4bba30STeresa Johnson
773d4bba30STeresa Johnson #if SANITIZER_INTERCEPT_REALLOCARRAY
INTERCEPTOR(void *,reallocarray,void * ptr,uptr nmemb,uptr size)783d4bba30STeresa Johnson INTERCEPTOR(void *, reallocarray, void *ptr, uptr nmemb, uptr size) {
793d4bba30STeresa Johnson ENSURE_MEMPROF_INITED();
803d4bba30STeresa Johnson GET_STACK_TRACE_MALLOC;
813d4bba30STeresa Johnson return memprof_reallocarray(ptr, nmemb, size, &stack);
823d4bba30STeresa Johnson }
833d4bba30STeresa Johnson #endif // SANITIZER_INTERCEPT_REALLOCARRAY
843d4bba30STeresa Johnson
853d4bba30STeresa Johnson #if SANITIZER_INTERCEPT_MEMALIGN
INTERCEPTOR(void *,memalign,uptr boundary,uptr size)863d4bba30STeresa Johnson INTERCEPTOR(void *, memalign, uptr boundary, uptr size) {
873d4bba30STeresa Johnson GET_STACK_TRACE_MALLOC;
883d4bba30STeresa Johnson return memprof_memalign(boundary, size, &stack, FROM_MALLOC);
893d4bba30STeresa Johnson }
903d4bba30STeresa Johnson
INTERCEPTOR(void *,__libc_memalign,uptr boundary,uptr size)913d4bba30STeresa Johnson INTERCEPTOR(void *, __libc_memalign, uptr boundary, uptr size) {
923d4bba30STeresa Johnson GET_STACK_TRACE_MALLOC;
933d4bba30STeresa Johnson void *res = memprof_memalign(boundary, size, &stack, FROM_MALLOC);
943d4bba30STeresa Johnson DTLS_on_libc_memalign(res, size);
953d4bba30STeresa Johnson return res;
963d4bba30STeresa Johnson }
973d4bba30STeresa Johnson #endif // SANITIZER_INTERCEPT_MEMALIGN
983d4bba30STeresa Johnson
993d4bba30STeresa Johnson #if SANITIZER_INTERCEPT_ALIGNED_ALLOC
INTERCEPTOR(void *,aligned_alloc,uptr boundary,uptr size)1003d4bba30STeresa Johnson INTERCEPTOR(void *, aligned_alloc, uptr boundary, uptr size) {
1013d4bba30STeresa Johnson GET_STACK_TRACE_MALLOC;
1023d4bba30STeresa Johnson return memprof_aligned_alloc(boundary, size, &stack);
1033d4bba30STeresa Johnson }
1043d4bba30STeresa Johnson #endif // SANITIZER_INTERCEPT_ALIGNED_ALLOC
1053d4bba30STeresa Johnson
INTERCEPTOR(uptr,malloc_usable_size,void * ptr)1063d4bba30STeresa Johnson INTERCEPTOR(uptr, malloc_usable_size, void *ptr) {
1073d4bba30STeresa Johnson GET_CURRENT_PC_BP_SP;
1083d4bba30STeresa Johnson (void)sp;
1093d4bba30STeresa Johnson return memprof_malloc_usable_size(ptr, pc, bp);
1103d4bba30STeresa Johnson }
1113d4bba30STeresa Johnson
1123d4bba30STeresa Johnson #if SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO
1133d4bba30STeresa Johnson // We avoid including malloc.h for portability reasons.
1143d4bba30STeresa Johnson // man mallinfo says the fields are "long", but the implementation uses int.
1153d4bba30STeresa Johnson // It doesn't matter much -- we just need to make sure that the libc's mallinfo
1163d4bba30STeresa Johnson // is not called.
1173d4bba30STeresa Johnson struct fake_mallinfo {
1183d4bba30STeresa Johnson int x[10];
1193d4bba30STeresa Johnson };
1203d4bba30STeresa Johnson
INTERCEPTOR(struct fake_mallinfo,mallinfo,void)1213d4bba30STeresa Johnson INTERCEPTOR(struct fake_mallinfo, mallinfo, void) {
1223d4bba30STeresa Johnson struct fake_mallinfo res;
1233d4bba30STeresa Johnson REAL(memset)(&res, 0, sizeof(res));
1243d4bba30STeresa Johnson return res;
1253d4bba30STeresa Johnson }
1263d4bba30STeresa Johnson
INTERCEPTOR(int,mallopt,int cmd,int value)1273d4bba30STeresa Johnson INTERCEPTOR(int, mallopt, int cmd, int value) { return 0; }
1283d4bba30STeresa Johnson #endif // SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO
1293d4bba30STeresa Johnson
INTERCEPTOR(int,posix_memalign,void ** memptr,uptr alignment,uptr size)1303d4bba30STeresa Johnson INTERCEPTOR(int, posix_memalign, void **memptr, uptr alignment, uptr size) {
1313d4bba30STeresa Johnson GET_STACK_TRACE_MALLOC;
1323d4bba30STeresa Johnson return memprof_posix_memalign(memptr, alignment, size, &stack);
1333d4bba30STeresa Johnson }
1343d4bba30STeresa Johnson
INTERCEPTOR(void *,valloc,uptr size)1353d4bba30STeresa Johnson INTERCEPTOR(void *, valloc, uptr size) {
1363d4bba30STeresa Johnson GET_STACK_TRACE_MALLOC;
1373d4bba30STeresa Johnson return memprof_valloc(size, &stack);
1383d4bba30STeresa Johnson }
1393d4bba30STeresa Johnson
1403d4bba30STeresa Johnson #if SANITIZER_INTERCEPT_PVALLOC
INTERCEPTOR(void *,pvalloc,uptr size)1413d4bba30STeresa Johnson INTERCEPTOR(void *, pvalloc, uptr size) {
1423d4bba30STeresa Johnson GET_STACK_TRACE_MALLOC;
1433d4bba30STeresa Johnson return memprof_pvalloc(size, &stack);
1443d4bba30STeresa Johnson }
1453d4bba30STeresa Johnson #endif // SANITIZER_INTERCEPT_PVALLOC
1463d4bba30STeresa Johnson
INTERCEPTOR(void,malloc_stats,void)1473d4bba30STeresa Johnson INTERCEPTOR(void, malloc_stats, void) { __memprof_print_accumulated_stats(); }
1483d4bba30STeresa Johnson
1493d4bba30STeresa Johnson namespace __memprof {
ReplaceSystemMalloc()1503d4bba30STeresa Johnson void ReplaceSystemMalloc() {}
1513d4bba30STeresa Johnson } // namespace __memprof
152