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 25 using namespace __memprof; 26 27 // Fake std::nothrow_t and std::align_val_t to avoid including <new>. 28 namespace std { 29 struct nothrow_t {}; 30 enum 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 46 CXX_OPERATOR_ATTRIBUTE 47 void *operator new(size_t size) { 48 OPERATOR_NEW_BODY(FROM_NEW, false /*nothrow*/); 49 } 50 CXX_OPERATOR_ATTRIBUTE 51 void *operator new[](size_t size) { 52 OPERATOR_NEW_BODY(FROM_NEW_BR, false /*nothrow*/); 53 } 54 CXX_OPERATOR_ATTRIBUTE 55 void *operator new(size_t size, std::nothrow_t const &) { 56 OPERATOR_NEW_BODY(FROM_NEW, true /*nothrow*/); 57 } 58 CXX_OPERATOR_ATTRIBUTE 59 void *operator new[](size_t size, std::nothrow_t const &) { 60 OPERATOR_NEW_BODY(FROM_NEW_BR, true /*nothrow*/); 61 } 62 CXX_OPERATOR_ATTRIBUTE 63 void *operator new(size_t size, std::align_val_t align) { 64 OPERATOR_NEW_BODY_ALIGN(FROM_NEW, false /*nothrow*/); 65 } 66 CXX_OPERATOR_ATTRIBUTE 67 void *operator new[](size_t size, std::align_val_t align) { 68 OPERATOR_NEW_BODY_ALIGN(FROM_NEW_BR, false /*nothrow*/); 69 } 70 CXX_OPERATOR_ATTRIBUTE 71 void *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 } 75 CXX_OPERATOR_ATTRIBUTE 76 void *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 97 CXX_OPERATOR_ATTRIBUTE 98 void operator delete(void *ptr)NOEXCEPT { OPERATOR_DELETE_BODY(FROM_NEW); } 99 CXX_OPERATOR_ATTRIBUTE 100 void operator delete[](void *ptr) NOEXCEPT { 101 OPERATOR_DELETE_BODY(FROM_NEW_BR); 102 } 103 CXX_OPERATOR_ATTRIBUTE 104 void operator delete(void *ptr, std::nothrow_t const &) { 105 OPERATOR_DELETE_BODY(FROM_NEW); 106 } 107 CXX_OPERATOR_ATTRIBUTE 108 void operator delete[](void *ptr, std::nothrow_t const &) { 109 OPERATOR_DELETE_BODY(FROM_NEW_BR); 110 } 111 CXX_OPERATOR_ATTRIBUTE 112 void operator delete(void *ptr, size_t size)NOEXCEPT { 113 OPERATOR_DELETE_BODY_SIZE(FROM_NEW); 114 } 115 CXX_OPERATOR_ATTRIBUTE 116 void operator delete[](void *ptr, size_t size) NOEXCEPT { 117 OPERATOR_DELETE_BODY_SIZE(FROM_NEW_BR); 118 } 119 CXX_OPERATOR_ATTRIBUTE 120 void operator delete(void *ptr, std::align_val_t align)NOEXCEPT { 121 OPERATOR_DELETE_BODY_ALIGN(FROM_NEW); 122 } 123 CXX_OPERATOR_ATTRIBUTE 124 void operator delete[](void *ptr, std::align_val_t align) NOEXCEPT { 125 OPERATOR_DELETE_BODY_ALIGN(FROM_NEW_BR); 126 } 127 CXX_OPERATOR_ATTRIBUTE 128 void operator delete(void *ptr, std::align_val_t align, 129 std::nothrow_t const &) { 130 OPERATOR_DELETE_BODY_ALIGN(FROM_NEW); 131 } 132 CXX_OPERATOR_ATTRIBUTE 133 void operator delete[](void *ptr, std::align_val_t align, 134 std::nothrow_t const &) { 135 OPERATOR_DELETE_BODY_ALIGN(FROM_NEW_BR); 136 } 137 CXX_OPERATOR_ATTRIBUTE 138 void operator delete(void *ptr, size_t size, std::align_val_t align)NOEXCEPT { 139 OPERATOR_DELETE_BODY_SIZE_ALIGN(FROM_NEW); 140 } 141 CXX_OPERATOR_ATTRIBUTE 142 void 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