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