1//===-- memprof_interceptors.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-exception 6// 7//===----------------------------------------------------------------------===// 8// 9// This file is a part of MemProfiler, a memory profiler. 10// 11// Interceptors for operators new and delete. 12//===----------------------------------------------------------------------===// 13 14#include "memprof_allocator.h" 15#include "memprof_internal.h" 16#include "memprof_stack.h" 17#include "sanitizer_common/sanitizer_allocator_report.h" 18 19#include "interception/interception.h" 20 21#include <stddef.h> 22 23#define CXX_OPERATOR_ATTRIBUTE INTERCEPTOR_ATTRIBUTE 24 25using namespace __memprof; 26 27// Fake std::nothrow_t and std::align_val_t to avoid including <new>. 28namespace std { 29struct nothrow_t {}; 30enum class align_val_t : size_t {}; 31} // namespace std 32 33#define OPERATOR_NEW_BODY(type, nothrow) \ 34 GET_STACK_TRACE_MALLOC; \ 35 void *res = memprof_memalign(0, size, &stack, type); \ 36 if (!nothrow && UNLIKELY(!res)) \ 37 ReportOutOfMemory(size, &stack); \ 38 return res; 39#define OPERATOR_NEW_BODY_ALIGN(type, nothrow) \ 40 GET_STACK_TRACE_MALLOC; \ 41 void *res = memprof_memalign((uptr)align, size, &stack, type); \ 42 if (!nothrow && UNLIKELY(!res)) \ 43 ReportOutOfMemory(size, &stack); \ 44 return res; 45 46CXX_OPERATOR_ATTRIBUTE 47void *operator new(size_t size) { 48 OPERATOR_NEW_BODY(FROM_NEW, false /*nothrow*/); 49} 50CXX_OPERATOR_ATTRIBUTE 51void *operator new[](size_t size) { 52 OPERATOR_NEW_BODY(FROM_NEW_BR, false /*nothrow*/); 53} 54CXX_OPERATOR_ATTRIBUTE 55void *operator new(size_t size, std::nothrow_t const &) { 56 OPERATOR_NEW_BODY(FROM_NEW, true /*nothrow*/); 57} 58CXX_OPERATOR_ATTRIBUTE 59void *operator new[](size_t size, std::nothrow_t const &) { 60 OPERATOR_NEW_BODY(FROM_NEW_BR, true /*nothrow*/); 61} 62CXX_OPERATOR_ATTRIBUTE 63void *operator new(size_t size, std::align_val_t align) { 64 OPERATOR_NEW_BODY_ALIGN(FROM_NEW, false /*nothrow*/); 65} 66CXX_OPERATOR_ATTRIBUTE 67void *operator new[](size_t size, std::align_val_t align) { 68 OPERATOR_NEW_BODY_ALIGN(FROM_NEW_BR, false /*nothrow*/); 69} 70CXX_OPERATOR_ATTRIBUTE 71void *operator new(size_t size, std::align_val_t align, 72 std::nothrow_t const &) { 73 OPERATOR_NEW_BODY_ALIGN(FROM_NEW, true /*nothrow*/); 74} 75CXX_OPERATOR_ATTRIBUTE 76void *operator new[](size_t size, std::align_val_t align, 77 std::nothrow_t const &) { 78 OPERATOR_NEW_BODY_ALIGN(FROM_NEW_BR, true /*nothrow*/); 79} 80 81#define OPERATOR_DELETE_BODY(type) \ 82 GET_STACK_TRACE_FREE; \ 83 memprof_delete(ptr, 0, 0, &stack, type); 84 85#define OPERATOR_DELETE_BODY_SIZE(type) \ 86 GET_STACK_TRACE_FREE; \ 87 memprof_delete(ptr, size, 0, &stack, type); 88 89#define OPERATOR_DELETE_BODY_ALIGN(type) \ 90 GET_STACK_TRACE_FREE; \ 91 memprof_delete(ptr, 0, static_cast<uptr>(align), &stack, type); 92 93#define OPERATOR_DELETE_BODY_SIZE_ALIGN(type) \ 94 GET_STACK_TRACE_FREE; \ 95 memprof_delete(ptr, size, static_cast<uptr>(align), &stack, type); 96 97CXX_OPERATOR_ATTRIBUTE 98void operator delete(void *ptr)NOEXCEPT { OPERATOR_DELETE_BODY(FROM_NEW); } 99CXX_OPERATOR_ATTRIBUTE 100void operator delete[](void *ptr) NOEXCEPT { 101 OPERATOR_DELETE_BODY(FROM_NEW_BR); 102} 103CXX_OPERATOR_ATTRIBUTE 104void operator delete(void *ptr, std::nothrow_t const &) { 105 OPERATOR_DELETE_BODY(FROM_NEW); 106} 107CXX_OPERATOR_ATTRIBUTE 108void operator delete[](void *ptr, std::nothrow_t const &) { 109 OPERATOR_DELETE_BODY(FROM_NEW_BR); 110} 111CXX_OPERATOR_ATTRIBUTE 112void operator delete(void *ptr, size_t size)NOEXCEPT { 113 OPERATOR_DELETE_BODY_SIZE(FROM_NEW); 114} 115CXX_OPERATOR_ATTRIBUTE 116void operator delete[](void *ptr, size_t size) NOEXCEPT { 117 OPERATOR_DELETE_BODY_SIZE(FROM_NEW_BR); 118} 119CXX_OPERATOR_ATTRIBUTE 120void operator delete(void *ptr, std::align_val_t align)NOEXCEPT { 121 OPERATOR_DELETE_BODY_ALIGN(FROM_NEW); 122} 123CXX_OPERATOR_ATTRIBUTE 124void operator delete[](void *ptr, std::align_val_t align) NOEXCEPT { 125 OPERATOR_DELETE_BODY_ALIGN(FROM_NEW_BR); 126} 127CXX_OPERATOR_ATTRIBUTE 128void operator delete(void *ptr, std::align_val_t align, 129 std::nothrow_t const &) { 130 OPERATOR_DELETE_BODY_ALIGN(FROM_NEW); 131} 132CXX_OPERATOR_ATTRIBUTE 133void operator delete[](void *ptr, std::align_val_t align, 134 std::nothrow_t const &) { 135 OPERATOR_DELETE_BODY_ALIGN(FROM_NEW_BR); 136} 137CXX_OPERATOR_ATTRIBUTE 138void operator delete(void *ptr, size_t size, std::align_val_t align)NOEXCEPT { 139 OPERATOR_DELETE_BODY_SIZE_ALIGN(FROM_NEW); 140} 141CXX_OPERATOR_ATTRIBUTE 142void operator delete[](void *ptr, size_t size, 143 std::align_val_t align) NOEXCEPT { 144 OPERATOR_DELETE_BODY_SIZE_ALIGN(FROM_NEW_BR); 145} 146