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 20using namespace __tsan; 21 22namespace std { 23struct nothrow_t {}; 24enum class align_val_t: __sanitizer::uptr {}; 25} // namespace std 26 27DECLARE_REAL(void *, malloc, uptr size) 28DECLARE_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 61SANITIZER_INTERFACE_ATTRIBUTE 62void *operator new(__sanitizer::uptr size); 63void *operator new(__sanitizer::uptr size) { 64 OPERATOR_NEW_BODY(_Znwm, false /*nothrow*/); 65} 66 67SANITIZER_INTERFACE_ATTRIBUTE 68void *operator new[](__sanitizer::uptr size); 69void *operator new[](__sanitizer::uptr size) { 70 OPERATOR_NEW_BODY(_Znam, false /*nothrow*/); 71} 72 73SANITIZER_INTERFACE_ATTRIBUTE 74void *operator new(__sanitizer::uptr size, std::nothrow_t const&); 75void *operator new(__sanitizer::uptr size, std::nothrow_t const&) { 76 OPERATOR_NEW_BODY(_ZnwmRKSt9nothrow_t, true /*nothrow*/); 77} 78 79SANITIZER_INTERFACE_ATTRIBUTE 80void *operator new[](__sanitizer::uptr size, std::nothrow_t const&); 81void *operator new[](__sanitizer::uptr size, std::nothrow_t const&) { 82 OPERATOR_NEW_BODY(_ZnamRKSt9nothrow_t, true /*nothrow*/); 83} 84 85SANITIZER_INTERFACE_ATTRIBUTE 86void *operator new(__sanitizer::uptr size, std::align_val_t align); 87void *operator new(__sanitizer::uptr size, std::align_val_t align) { 88 OPERATOR_NEW_BODY_ALIGN(_ZnwmSt11align_val_t, false /*nothrow*/); 89} 90 91SANITIZER_INTERFACE_ATTRIBUTE 92void *operator new[](__sanitizer::uptr size, std::align_val_t align); 93void *operator new[](__sanitizer::uptr size, std::align_val_t align) { 94 OPERATOR_NEW_BODY_ALIGN(_ZnamSt11align_val_t, false /*nothrow*/); 95} 96 97SANITIZER_INTERFACE_ATTRIBUTE 98void *operator new(__sanitizer::uptr size, std::align_val_t align, 99 std::nothrow_t const&); 100void *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 106SANITIZER_INTERFACE_ATTRIBUTE 107void *operator new[](__sanitizer::uptr size, std::align_val_t align, 108 std::nothrow_t const&); 109void *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 123SANITIZER_INTERFACE_ATTRIBUTE 124void operator delete(void *ptr) NOEXCEPT; 125void operator delete(void *ptr) NOEXCEPT { 126 OPERATOR_DELETE_BODY(_ZdlPv); 127} 128 129SANITIZER_INTERFACE_ATTRIBUTE 130void operator delete[](void *ptr) NOEXCEPT; 131void operator delete[](void *ptr) NOEXCEPT { 132 OPERATOR_DELETE_BODY(_ZdaPv); 133} 134 135SANITIZER_INTERFACE_ATTRIBUTE 136void operator delete(void *ptr, std::nothrow_t const&); 137void operator delete(void *ptr, std::nothrow_t const&) { 138 OPERATOR_DELETE_BODY(_ZdlPvRKSt9nothrow_t); 139} 140 141SANITIZER_INTERFACE_ATTRIBUTE 142void operator delete[](void *ptr, std::nothrow_t const&); 143void operator delete[](void *ptr, std::nothrow_t const&) { 144 OPERATOR_DELETE_BODY(_ZdaPvRKSt9nothrow_t); 145} 146 147SANITIZER_INTERFACE_ATTRIBUTE 148void operator delete(void *ptr, __sanitizer::uptr size) NOEXCEPT; 149void operator delete(void *ptr, __sanitizer::uptr size) NOEXCEPT { 150 OPERATOR_DELETE_BODY(_ZdlPvm); 151} 152 153SANITIZER_INTERFACE_ATTRIBUTE 154void operator delete[](void *ptr, __sanitizer::uptr size) NOEXCEPT; 155void operator delete[](void *ptr, __sanitizer::uptr size) NOEXCEPT { 156 OPERATOR_DELETE_BODY(_ZdaPvm); 157} 158 159SANITIZER_INTERFACE_ATTRIBUTE 160void operator delete(void *ptr, std::align_val_t align) NOEXCEPT; 161void operator delete(void *ptr, std::align_val_t align) NOEXCEPT { 162 OPERATOR_DELETE_BODY(_ZdlPvSt11align_val_t); 163} 164 165SANITIZER_INTERFACE_ATTRIBUTE 166void operator delete[](void *ptr, std::align_val_t align) NOEXCEPT; 167void operator delete[](void *ptr, std::align_val_t align) NOEXCEPT { 168 OPERATOR_DELETE_BODY(_ZdaPvSt11align_val_t); 169} 170 171SANITIZER_INTERFACE_ATTRIBUTE 172void operator delete(void *ptr, std::align_val_t align, std::nothrow_t const&); 173void operator delete(void *ptr, std::align_val_t align, std::nothrow_t const&) { 174 OPERATOR_DELETE_BODY(_ZdlPvSt11align_val_tRKSt9nothrow_t); 175} 176 177SANITIZER_INTERFACE_ATTRIBUTE 178void operator delete[](void *ptr, std::align_val_t align, 179 std::nothrow_t const&); 180void operator delete[](void *ptr, std::align_val_t align, 181 std::nothrow_t const&) { 182 OPERATOR_DELETE_BODY(_ZdaPvSt11align_val_tRKSt9nothrow_t); 183} 184 185SANITIZER_INTERFACE_ATTRIBUTE 186void operator delete(void *ptr, __sanitizer::uptr size, 187 std::align_val_t align) NOEXCEPT; 188void operator delete(void *ptr, __sanitizer::uptr size, 189 std::align_val_t align) NOEXCEPT { 190 OPERATOR_DELETE_BODY(_ZdlPvmSt11align_val_t); 191} 192 193SANITIZER_INTERFACE_ATTRIBUTE 194void operator delete[](void *ptr, __sanitizer::uptr size, 195 std::align_val_t align) NOEXCEPT; 196void operator delete[](void *ptr, __sanitizer::uptr size, 197 std::align_val_t align) NOEXCEPT { 198 OPERATOR_DELETE_BODY(_ZdaPvmSt11align_val_t); 199} 200