154263Sshin//===-- memprof_interceptors.cpp -----------------------------------------===//
254263Sshin//
354263Sshin// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
454263Sshin// See https://llvm.org/LICENSE.txt for license information.
554263Sshin// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
654263Sshin//
754263Sshin//===----------------------------------------------------------------------===//
854263Sshin//
954263Sshin// This file is a part of MemProfiler, a memory profiler.
1054263Sshin//
1154263Sshin// Interceptors for operators new and delete.
1254263Sshin//===----------------------------------------------------------------------===//
1354263Sshin
1454263Sshin#include "memprof_allocator.h"
1554263Sshin#include "memprof_internal.h"
1654263Sshin#include "memprof_stack.h"
1754263Sshin#include "sanitizer_common/sanitizer_allocator_report.h"
1854263Sshin
1954263Sshin#include "interception/interception.h"
2054263Sshin
2154263Sshin#include <stddef.h>
2254263Sshin
2354263Sshin#define CXX_OPERATOR_ATTRIBUTE INTERCEPTOR_ATTRIBUTE
2454263Sshin
2554263Sshinusing namespace __memprof;
2654263Sshin
2754263Sshin// Fake std::nothrow_t and std::align_val_t to avoid including <new>.
2854263Sshinnamespace std {
2954263Sshinstruct nothrow_t {};
3054263Sshinenum class align_val_t : size_t {};
3154263Sshin} // namespace std
3254263Sshin
3354263Sshin#define OPERATOR_NEW_BODY(type, nothrow)                                       \
3454263Sshin  GET_STACK_TRACE_MALLOC;                                                      \
3554263Sshin  void *res = memprof_memalign(0, size, &stack, type);                         \
3654263Sshin  if (!nothrow && UNLIKELY(!res))                                              \
3754263Sshin    ReportOutOfMemory(size, &stack);                                           \
3854263Sshin  return res;
3954263Sshin#define OPERATOR_NEW_BODY_ALIGN(type, nothrow)                                 \
4054263Sshin  GET_STACK_TRACE_MALLOC;                                                      \
4154263Sshin  void *res = memprof_memalign((uptr)align, size, &stack, type);               \
4254263Sshin  if (!nothrow && UNLIKELY(!res))                                              \
4354263Sshin    ReportOutOfMemory(size, &stack);                                           \
4454263Sshin  return res;
4554263Sshin
4654263SshinCXX_OPERATOR_ATTRIBUTE
4754263Sshinvoid *operator new(size_t size) {
4854263Sshin  OPERATOR_NEW_BODY(FROM_NEW, false /*nothrow*/);
4954263Sshin}
5054263SshinCXX_OPERATOR_ATTRIBUTE
5154263Sshinvoid *operator new[](size_t size) {
5254263Sshin  OPERATOR_NEW_BODY(FROM_NEW_BR, false /*nothrow*/);
5354263Sshin}
5454263SshinCXX_OPERATOR_ATTRIBUTE
5554263Sshinvoid *operator new(size_t size, std::nothrow_t const &) {
5654263Sshin  OPERATOR_NEW_BODY(FROM_NEW, true /*nothrow*/);
5754263Sshin}
5855009SshinCXX_OPERATOR_ATTRIBUTE
5955009Sshinvoid *operator new[](size_t size, std::nothrow_t const &) {
6054263Sshin  OPERATOR_NEW_BODY(FROM_NEW_BR, true /*nothrow*/);
6154263Sshin}
6254263SshinCXX_OPERATOR_ATTRIBUTE
6354263Sshinvoid *operator new(size_t size, std::align_val_t align) {
6454263Sshin  OPERATOR_NEW_BODY_ALIGN(FROM_NEW, false /*nothrow*/);
6554263Sshin}
6654263SshinCXX_OPERATOR_ATTRIBUTE
6754263Sshinvoid *operator new[](size_t size, std::align_val_t align) {
6854263Sshin  OPERATOR_NEW_BODY_ALIGN(FROM_NEW_BR, false /*nothrow*/);
6954263Sshin}
7054263SshinCXX_OPERATOR_ATTRIBUTE
7154263Sshinvoid *operator new(size_t size, std::align_val_t align,
7254263Sshin                   std::nothrow_t const &) {
7354263Sshin  OPERATOR_NEW_BODY_ALIGN(FROM_NEW, true /*nothrow*/);
7454263Sshin}
7554263SshinCXX_OPERATOR_ATTRIBUTE
7654263Sshinvoid *operator new[](size_t size, std::align_val_t align,
7754263Sshin                     std::nothrow_t const &) {
7855009Sshin  OPERATOR_NEW_BODY_ALIGN(FROM_NEW_BR, true /*nothrow*/);
7954263Sshin}
8054263Sshin
8154263Sshin#define OPERATOR_DELETE_BODY(type)                                             \
8254263Sshin  GET_STACK_TRACE_FREE;                                                        \
8354263Sshin  memprof_delete(ptr, 0, 0, &stack, type);
8454263Sshin
8554263Sshin#define OPERATOR_DELETE_BODY_SIZE(type)                                        \
8654263Sshin  GET_STACK_TRACE_FREE;                                                        \
8754263Sshin  memprof_delete(ptr, size, 0, &stack, type);
8854263Sshin
8954263Sshin#define OPERATOR_DELETE_BODY_ALIGN(type)                                       \
9054263Sshin  GET_STACK_TRACE_FREE;                                                        \
9154263Sshin  memprof_delete(ptr, 0, static_cast<uptr>(align), &stack, type);
9254263Sshin
9354263Sshin#define OPERATOR_DELETE_BODY_SIZE_ALIGN(type)                                  \
9454263Sshin  GET_STACK_TRACE_FREE;                                                        \
9554263Sshin  memprof_delete(ptr, size, static_cast<uptr>(align), &stack, type);
9654263Sshin
9754263SshinCXX_OPERATOR_ATTRIBUTE
9854263Sshinvoid operator delete(void *ptr)NOEXCEPT { OPERATOR_DELETE_BODY(FROM_NEW); }
9954263SshinCXX_OPERATOR_ATTRIBUTE
10055009Sshinvoid operator delete[](void *ptr) NOEXCEPT {
10154263Sshin  OPERATOR_DELETE_BODY(FROM_NEW_BR);
10254263Sshin}
10354263SshinCXX_OPERATOR_ATTRIBUTE
10454263Sshinvoid operator delete(void *ptr, std::nothrow_t const &) {
10554263Sshin  OPERATOR_DELETE_BODY(FROM_NEW);
10654263Sshin}
10754263SshinCXX_OPERATOR_ATTRIBUTE
10854263Sshinvoid operator delete[](void *ptr, std::nothrow_t const &) {
10954263Sshin  OPERATOR_DELETE_BODY(FROM_NEW_BR);
11054263Sshin}
11154263SshinCXX_OPERATOR_ATTRIBUTE
11254263Sshinvoid operator delete(void *ptr, size_t size)NOEXCEPT {
11354263Sshin  OPERATOR_DELETE_BODY_SIZE(FROM_NEW);
11455009Sshin}
11554263SshinCXX_OPERATOR_ATTRIBUTE
11654263Sshinvoid operator delete[](void *ptr, size_t size) NOEXCEPT {
11754263Sshin  OPERATOR_DELETE_BODY_SIZE(FROM_NEW_BR);
11854263Sshin}
11954263SshinCXX_OPERATOR_ATTRIBUTE
12054263Sshinvoid operator delete(void *ptr, std::align_val_t align)NOEXCEPT {
12154263Sshin  OPERATOR_DELETE_BODY_ALIGN(FROM_NEW);
12254263Sshin}
12354263SshinCXX_OPERATOR_ATTRIBUTE
12454263Sshinvoid operator delete[](void *ptr, std::align_val_t align) NOEXCEPT {
12554263Sshin  OPERATOR_DELETE_BODY_ALIGN(FROM_NEW_BR);
12654263Sshin}
12754263SshinCXX_OPERATOR_ATTRIBUTE
12854263Sshinvoid operator delete(void *ptr, std::align_val_t align,
12954263Sshin                     std::nothrow_t const &) {
13054263Sshin  OPERATOR_DELETE_BODY_ALIGN(FROM_NEW);
13154263Sshin}
13254263SshinCXX_OPERATOR_ATTRIBUTE
13354263Sshinvoid operator delete[](void *ptr, std::align_val_t align,
13454263Sshin                       std::nothrow_t const &) {
13554263Sshin  OPERATOR_DELETE_BODY_ALIGN(FROM_NEW_BR);
13654263Sshin}
13754263SshinCXX_OPERATOR_ATTRIBUTE
13854263Sshinvoid operator delete(void *ptr, size_t size, std::align_val_t align)NOEXCEPT {
13954263Sshin  OPERATOR_DELETE_BODY_SIZE_ALIGN(FROM_NEW);
14054263Sshin}
14154263SshinCXX_OPERATOR_ATTRIBUTE
14254263Sshinvoid operator delete[](void *ptr, size_t size,
14354263Sshin                       std::align_val_t align) NOEXCEPT {
14454263Sshin  OPERATOR_DELETE_BODY_SIZE_ALIGN(FROM_NEW_BR);
14554263Sshin}
14654263Sshin