1 //===-- tsan_new_delete.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 ThreadSanitizer (TSan), a race detector. 10 // 11 // Interceptors for operators new and delete. 12 //===----------------------------------------------------------------------===// 13 #include "interception/interception.h" 14 #include "sanitizer_common/sanitizer_allocator.h" 15 #include "sanitizer_common/sanitizer_allocator_report.h" 16 #include "sanitizer_common/sanitizer_internal_defs.h" 17 #include "tsan_interceptors.h" 18 #include "tsan_rtl.h" 19 20 using namespace __tsan; 21 22 namespace std { 23 struct nothrow_t {}; 24 enum class align_val_t: __sanitizer::uptr {}; 25 } // namespace std 26 27 DECLARE_REAL(void *, malloc, uptr size) 28 DECLARE_REAL(void, free, void *ptr) 29 30 // TODO(alekseys): throw std::bad_alloc instead of dying on OOM. 31 #define OPERATOR_NEW_BODY(mangled_name, nothrow) \ 32 if (in_symbolizer()) \ 33 return InternalAlloc(size); \ 34 void *p = 0; \ 35 { \ 36 SCOPED_INTERCEPTOR_RAW(mangled_name, size); \ 37 p = user_alloc(thr, pc, size); \ 38 if (!nothrow && UNLIKELY(!p)) { \ 39 GET_STACK_TRACE_FATAL(thr, pc); \ 40 ReportOutOfMemory(size, &stack); \ 41 } \ 42 } \ 43 invoke_malloc_hook(p, size); \ 44 return p; 45 46 #define OPERATOR_NEW_BODY_ALIGN(mangled_name, nothrow) \ 47 if (in_symbolizer()) \ 48 return InternalAlloc(size, nullptr, (uptr)align); \ 49 void *p = 0; \ 50 { \ 51 SCOPED_INTERCEPTOR_RAW(mangled_name, size); \ 52 p = user_memalign(thr, pc, (uptr)align, size); \ 53 if (!nothrow && UNLIKELY(!p)) { \ 54 GET_STACK_TRACE_FATAL(thr, pc); \ 55 ReportOutOfMemory(size, &stack); \ 56 } \ 57 } \ 58 invoke_malloc_hook(p, size); \ 59 return p; 60 61 SANITIZER_INTERFACE_ATTRIBUTE 62 void *operator new(__sanitizer::uptr size); 63 void *operator new(__sanitizer::uptr size) { 64 OPERATOR_NEW_BODY(_Znwm, false /*nothrow*/); 65 } 66 67 SANITIZER_INTERFACE_ATTRIBUTE 68 void *operator new[](__sanitizer::uptr size); 69 void *operator new[](__sanitizer::uptr size) { 70 OPERATOR_NEW_BODY(_Znam, false /*nothrow*/); 71 } 72 73 SANITIZER_INTERFACE_ATTRIBUTE 74 void *operator new(__sanitizer::uptr size, std::nothrow_t const&); 75 void *operator new(__sanitizer::uptr size, std::nothrow_t const&) { 76 OPERATOR_NEW_BODY(_ZnwmRKSt9nothrow_t, true /*nothrow*/); 77 } 78 79 SANITIZER_INTERFACE_ATTRIBUTE 80 void *operator new[](__sanitizer::uptr size, std::nothrow_t const&); 81 void *operator new[](__sanitizer::uptr size, std::nothrow_t const&) { 82 OPERATOR_NEW_BODY(_ZnamRKSt9nothrow_t, true /*nothrow*/); 83 } 84 85 SANITIZER_INTERFACE_ATTRIBUTE 86 void *operator new(__sanitizer::uptr size, std::align_val_t align); 87 void *operator new(__sanitizer::uptr size, std::align_val_t align) { 88 OPERATOR_NEW_BODY_ALIGN(_ZnwmSt11align_val_t, false /*nothrow*/); 89 } 90 91 SANITIZER_INTERFACE_ATTRIBUTE 92 void *operator new[](__sanitizer::uptr size, std::align_val_t align); 93 void *operator new[](__sanitizer::uptr size, std::align_val_t align) { 94 OPERATOR_NEW_BODY_ALIGN(_ZnamSt11align_val_t, false /*nothrow*/); 95 } 96 97 SANITIZER_INTERFACE_ATTRIBUTE 98 void *operator new(__sanitizer::uptr size, std::align_val_t align, 99 std::nothrow_t const&); 100 void *operator new(__sanitizer::uptr size, std::align_val_t align, 101 std::nothrow_t const&) { 102 OPERATOR_NEW_BODY_ALIGN(_ZnwmSt11align_val_tRKSt9nothrow_t, 103 true /*nothrow*/); 104 } 105 106 SANITIZER_INTERFACE_ATTRIBUTE 107 void *operator new[](__sanitizer::uptr size, std::align_val_t align, 108 std::nothrow_t const&); 109 void *operator new[](__sanitizer::uptr size, std::align_val_t align, 110 std::nothrow_t const&) { 111 OPERATOR_NEW_BODY_ALIGN(_ZnamSt11align_val_tRKSt9nothrow_t, 112 true /*nothrow*/); 113 } 114 115 #define OPERATOR_DELETE_BODY(mangled_name) \ 116 if (ptr == 0) return; \ 117 if (in_symbolizer()) \ 118 return InternalFree(ptr); \ 119 invoke_free_hook(ptr); \ 120 SCOPED_INTERCEPTOR_RAW(mangled_name, ptr); \ 121 user_free(thr, pc, ptr); 122 123 SANITIZER_INTERFACE_ATTRIBUTE 124 void operator delete(void *ptr) NOEXCEPT; 125 void operator delete(void *ptr) NOEXCEPT { 126 OPERATOR_DELETE_BODY(_ZdlPv); 127 } 128 129 SANITIZER_INTERFACE_ATTRIBUTE 130 void operator delete[](void *ptr) NOEXCEPT; 131 void operator delete[](void *ptr) NOEXCEPT { 132 OPERATOR_DELETE_BODY(_ZdaPv); 133 } 134 135 SANITIZER_INTERFACE_ATTRIBUTE 136 void operator delete(void *ptr, std::nothrow_t const&); 137 void operator delete(void *ptr, std::nothrow_t const&) { 138 OPERATOR_DELETE_BODY(_ZdlPvRKSt9nothrow_t); 139 } 140 141 SANITIZER_INTERFACE_ATTRIBUTE 142 void operator delete[](void *ptr, std::nothrow_t const&); 143 void operator delete[](void *ptr, std::nothrow_t const&) { 144 OPERATOR_DELETE_BODY(_ZdaPvRKSt9nothrow_t); 145 } 146 147 SANITIZER_INTERFACE_ATTRIBUTE 148 void operator delete(void *ptr, __sanitizer::uptr size) NOEXCEPT; 149 void operator delete(void *ptr, __sanitizer::uptr size) NOEXCEPT { 150 OPERATOR_DELETE_BODY(_ZdlPvm); 151 } 152 153 SANITIZER_INTERFACE_ATTRIBUTE 154 void operator delete[](void *ptr, __sanitizer::uptr size) NOEXCEPT; 155 void operator delete[](void *ptr, __sanitizer::uptr size) NOEXCEPT { 156 OPERATOR_DELETE_BODY(_ZdaPvm); 157 } 158 159 SANITIZER_INTERFACE_ATTRIBUTE 160 void operator delete(void *ptr, std::align_val_t align) NOEXCEPT; 161 void operator delete(void *ptr, std::align_val_t align) NOEXCEPT { 162 OPERATOR_DELETE_BODY(_ZdlPvSt11align_val_t); 163 } 164 165 SANITIZER_INTERFACE_ATTRIBUTE 166 void operator delete[](void *ptr, std::align_val_t align) NOEXCEPT; 167 void operator delete[](void *ptr, std::align_val_t align) NOEXCEPT { 168 OPERATOR_DELETE_BODY(_ZdaPvSt11align_val_t); 169 } 170 171 SANITIZER_INTERFACE_ATTRIBUTE 172 void operator delete(void *ptr, std::align_val_t align, std::nothrow_t const&); 173 void operator delete(void *ptr, std::align_val_t align, std::nothrow_t const&) { 174 OPERATOR_DELETE_BODY(_ZdlPvSt11align_val_tRKSt9nothrow_t); 175 } 176 177 SANITIZER_INTERFACE_ATTRIBUTE 178 void operator delete[](void *ptr, std::align_val_t align, 179 std::nothrow_t const&); 180 void operator delete[](void *ptr, std::align_val_t align, 181 std::nothrow_t const&) { 182 OPERATOR_DELETE_BODY(_ZdaPvSt11align_val_tRKSt9nothrow_t); 183 } 184 185 SANITIZER_INTERFACE_ATTRIBUTE 186 void operator delete(void *ptr, __sanitizer::uptr size, 187 std::align_val_t align) NOEXCEPT; 188 void operator delete(void *ptr, __sanitizer::uptr size, 189 std::align_val_t align) NOEXCEPT { 190 OPERATOR_DELETE_BODY(_ZdlPvmSt11align_val_t); 191 } 192 193 SANITIZER_INTERFACE_ATTRIBUTE 194 void operator delete[](void *ptr, __sanitizer::uptr size, 195 std::align_val_t align) NOEXCEPT; 196 void operator delete[](void *ptr, __sanitizer::uptr size, 197 std::align_val_t align) NOEXCEPT { 198 OPERATOR_DELETE_BODY(_ZdaPvmSt11align_val_t); 199 } 200