memprof_new_delete.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. //===-- memprof_interceptors.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 MemProfiler, a memory profiler.
  10. //
  11. // Interceptors for operators new and delete.
  12. //===----------------------------------------------------------------------===//
  13. #include "memprof_allocator.h"
  14. #include "memprof_internal.h"
  15. #include "memprof_stack.h"
  16. #include "sanitizer_common/sanitizer_allocator_report.h"
  17. #include "interception/interception.h"
  18. #include <stddef.h>
  19. #define CXX_OPERATOR_ATTRIBUTE INTERCEPTOR_ATTRIBUTE
  20. using namespace __memprof;
  21. // Fake std::nothrow_t and std::align_val_t to avoid including <new>.
  22. namespace std {
  23. struct nothrow_t {};
  24. enum class align_val_t : size_t {};
  25. } // namespace std
  26. #define OPERATOR_NEW_BODY(type, nothrow) \
  27. GET_STACK_TRACE_MALLOC; \
  28. void *res = memprof_memalign(0, size, &stack, type); \
  29. if (!nothrow && UNLIKELY(!res)) \
  30. ReportOutOfMemory(size, &stack); \
  31. return res;
  32. #define OPERATOR_NEW_BODY_ALIGN(type, nothrow) \
  33. GET_STACK_TRACE_MALLOC; \
  34. void *res = memprof_memalign((uptr)align, size, &stack, type); \
  35. if (!nothrow && UNLIKELY(!res)) \
  36. ReportOutOfMemory(size, &stack); \
  37. return res;
  38. CXX_OPERATOR_ATTRIBUTE
  39. void *operator new(size_t size) {
  40. OPERATOR_NEW_BODY(FROM_NEW, false /*nothrow*/);
  41. }
  42. CXX_OPERATOR_ATTRIBUTE
  43. void *operator new[](size_t size) {
  44. OPERATOR_NEW_BODY(FROM_NEW_BR, false /*nothrow*/);
  45. }
  46. CXX_OPERATOR_ATTRIBUTE
  47. void *operator new(size_t size, std::nothrow_t const &) {
  48. OPERATOR_NEW_BODY(FROM_NEW, true /*nothrow*/);
  49. }
  50. CXX_OPERATOR_ATTRIBUTE
  51. void *operator new[](size_t size, std::nothrow_t const &) {
  52. OPERATOR_NEW_BODY(FROM_NEW_BR, true /*nothrow*/);
  53. }
  54. CXX_OPERATOR_ATTRIBUTE
  55. void *operator new(size_t size, std::align_val_t align) {
  56. OPERATOR_NEW_BODY_ALIGN(FROM_NEW, false /*nothrow*/);
  57. }
  58. CXX_OPERATOR_ATTRIBUTE
  59. void *operator new[](size_t size, std::align_val_t align) {
  60. OPERATOR_NEW_BODY_ALIGN(FROM_NEW_BR, false /*nothrow*/);
  61. }
  62. CXX_OPERATOR_ATTRIBUTE
  63. void *operator new(size_t size, std::align_val_t align,
  64. std::nothrow_t const &) {
  65. OPERATOR_NEW_BODY_ALIGN(FROM_NEW, true /*nothrow*/);
  66. }
  67. CXX_OPERATOR_ATTRIBUTE
  68. void *operator new[](size_t size, std::align_val_t align,
  69. std::nothrow_t const &) {
  70. OPERATOR_NEW_BODY_ALIGN(FROM_NEW_BR, true /*nothrow*/);
  71. }
  72. #define OPERATOR_DELETE_BODY(type) \
  73. GET_STACK_TRACE_FREE; \
  74. memprof_delete(ptr, 0, 0, &stack, type);
  75. #define OPERATOR_DELETE_BODY_SIZE(type) \
  76. GET_STACK_TRACE_FREE; \
  77. memprof_delete(ptr, size, 0, &stack, type);
  78. #define OPERATOR_DELETE_BODY_ALIGN(type) \
  79. GET_STACK_TRACE_FREE; \
  80. memprof_delete(ptr, 0, static_cast<uptr>(align), &stack, type);
  81. #define OPERATOR_DELETE_BODY_SIZE_ALIGN(type) \
  82. GET_STACK_TRACE_FREE; \
  83. memprof_delete(ptr, size, static_cast<uptr>(align), &stack, type);
  84. CXX_OPERATOR_ATTRIBUTE
  85. void operator delete(void *ptr)NOEXCEPT { OPERATOR_DELETE_BODY(FROM_NEW); }
  86. CXX_OPERATOR_ATTRIBUTE
  87. void operator delete[](void *ptr) NOEXCEPT {
  88. OPERATOR_DELETE_BODY(FROM_NEW_BR);
  89. }
  90. CXX_OPERATOR_ATTRIBUTE
  91. void operator delete(void *ptr, std::nothrow_t const &) {
  92. OPERATOR_DELETE_BODY(FROM_NEW);
  93. }
  94. CXX_OPERATOR_ATTRIBUTE
  95. void operator delete[](void *ptr, std::nothrow_t const &) {
  96. OPERATOR_DELETE_BODY(FROM_NEW_BR);
  97. }
  98. CXX_OPERATOR_ATTRIBUTE
  99. void operator delete(void *ptr, size_t size)NOEXCEPT {
  100. OPERATOR_DELETE_BODY_SIZE(FROM_NEW);
  101. }
  102. CXX_OPERATOR_ATTRIBUTE
  103. void operator delete[](void *ptr, size_t size) NOEXCEPT {
  104. OPERATOR_DELETE_BODY_SIZE(FROM_NEW_BR);
  105. }
  106. CXX_OPERATOR_ATTRIBUTE
  107. void operator delete(void *ptr, std::align_val_t align)NOEXCEPT {
  108. OPERATOR_DELETE_BODY_ALIGN(FROM_NEW);
  109. }
  110. CXX_OPERATOR_ATTRIBUTE
  111. void operator delete[](void *ptr, std::align_val_t align) NOEXCEPT {
  112. OPERATOR_DELETE_BODY_ALIGN(FROM_NEW_BR);
  113. }
  114. CXX_OPERATOR_ATTRIBUTE
  115. void operator delete(void *ptr, std::align_val_t align,
  116. std::nothrow_t const &) {
  117. OPERATOR_DELETE_BODY_ALIGN(FROM_NEW);
  118. }
  119. CXX_OPERATOR_ATTRIBUTE
  120. void operator delete[](void *ptr, std::align_val_t align,
  121. std::nothrow_t const &) {
  122. OPERATOR_DELETE_BODY_ALIGN(FROM_NEW_BR);
  123. }
  124. CXX_OPERATOR_ATTRIBUTE
  125. void operator delete(void *ptr, size_t size, std::align_val_t align)NOEXCEPT {
  126. OPERATOR_DELETE_BODY_SIZE_ALIGN(FROM_NEW);
  127. }
  128. CXX_OPERATOR_ATTRIBUTE
  129. void operator delete[](void *ptr, size_t size,
  130. std::align_val_t align) NOEXCEPT {
  131. OPERATOR_DELETE_BODY_SIZE_ALIGN(FROM_NEW_BR);
  132. }