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