1 //===----------------------------------------------------------------------===// 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 #include "__cxxabi_config.h" 10 #include "abort_message.h" 11 #include "include/overridable_function.h" // from libc++ 12 #include <__memory/aligned_alloc.h> 13 #include <cstddef> 14 #include <cstdlib> 15 #include <new> 16 17 // Perform a few sanity checks on libc++ and libc++abi macros to ensure that 18 // the code below can be an exact copy of the code in libcxx/src/new.cpp. 19 #if !defined(_THROW_BAD_ALLOC) 20 # error The _THROW_BAD_ALLOC macro should be already defined by libc++ 21 #endif 22 23 #ifndef _LIBCPP_WEAK 24 # error The _LIBCPP_WEAK macro should be already defined by libc++ 25 #endif 26 27 #if defined(_LIBCXXABI_NO_EXCEPTIONS) != !_LIBCPP_HAS_EXCEPTIONS 28 # error libc++ and libc++abi seem to disagree on whether exceptions are enabled 29 #endif 30 31 inline void __throw_bad_alloc_shim() { 32 #if _LIBCPP_HAS_EXCEPTIONS 33 throw std::bad_alloc(); 34 #else 35 __abort_message("bad_alloc was thrown in -fno-exceptions mode"); 36 #endif 37 } 38 39 #define _LIBCPP_ASSERT_SHIM(expr, str) \ 40 do { \ 41 if (!expr) \ 42 __abort_message(str); \ 43 } while (false) 44 45 // ------------------ BEGIN COPY ------------------ 46 // Implement all new and delete operators as weak definitions 47 // in this shared library, so that they can be overridden by programs 48 // that define non-weak copies of the functions. 49 50 static void* operator_new_impl(std::size_t size) { 51 if (size == 0) 52 size = 1; 53 void* p; 54 while ((p = std::malloc(size)) == nullptr) { 55 // If malloc fails and there is a new_handler, 56 // call it to try free up memory. 57 std::new_handler nh = std::get_new_handler(); 58 if (nh) 59 nh(); 60 else 61 break; 62 } 63 return p; 64 } 65 66 _LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void* operator new(std::size_t size) _THROW_BAD_ALLOC { 67 void* p = operator_new_impl(size); 68 if (p == nullptr) 69 __throw_bad_alloc_shim(); 70 return p; 71 } 72 73 _LIBCPP_WEAK void* operator new(size_t size, const std::nothrow_t&) noexcept { 74 #if !_LIBCPP_HAS_EXCEPTIONS 75 # if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION 76 _LIBCPP_ASSERT_SHIM( 77 !std::__is_function_overridden(static_cast<void* (*)(std::size_t)>(&operator new)), 78 "libc++ was configured with exceptions disabled and `operator new(size_t)` has been overridden, " 79 "but `operator new(size_t, nothrow_t)` has not been overridden. This is problematic because " 80 "`operator new(size_t, nothrow_t)` must call `operator new(size_t)`, which will terminate in case " 81 "it fails to allocate, making it impossible for `operator new(size_t, nothrow_t)` to fulfill its " 82 "contract (since it should return nullptr upon failure). Please make sure you override " 83 "`operator new(size_t, nothrow_t)` as well."); 84 # endif 85 86 return operator_new_impl(size); 87 #else 88 void* p = nullptr; 89 try { 90 p = ::operator new(size); 91 } catch (...) { 92 } 93 return p; 94 #endif 95 } 96 97 _LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void* operator new[](size_t size) _THROW_BAD_ALLOC { 98 return ::operator new(size); 99 } 100 101 _LIBCPP_WEAK void* operator new[](size_t size, const std::nothrow_t&) noexcept { 102 #if !_LIBCPP_HAS_EXCEPTIONS 103 # if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION 104 _LIBCPP_ASSERT_SHIM( 105 !std::__is_function_overridden(static_cast<void* (*)(std::size_t)>(&operator new[])), 106 "libc++ was configured with exceptions disabled and `operator new[](size_t)` has been overridden, " 107 "but `operator new[](size_t, nothrow_t)` has not been overridden. This is problematic because " 108 "`operator new[](size_t, nothrow_t)` must call `operator new[](size_t)`, which will terminate in case " 109 "it fails to allocate, making it impossible for `operator new[](size_t, nothrow_t)` to fulfill its " 110 "contract (since it should return nullptr upon failure). Please make sure you override " 111 "`operator new[](size_t, nothrow_t)` as well."); 112 # endif 113 114 return operator_new_impl(size); 115 #else 116 void* p = nullptr; 117 try { 118 p = ::operator new[](size); 119 } catch (...) { 120 } 121 return p; 122 #endif 123 } 124 125 _LIBCPP_WEAK void operator delete(void* ptr) noexcept { std::free(ptr); } 126 127 _LIBCPP_WEAK void operator delete(void* ptr, const std::nothrow_t&) noexcept { ::operator delete(ptr); } 128 129 _LIBCPP_WEAK void operator delete(void* ptr, size_t) noexcept { ::operator delete(ptr); } 130 131 _LIBCPP_WEAK void operator delete[](void* ptr) noexcept { ::operator delete(ptr); } 132 133 _LIBCPP_WEAK void operator delete[](void* ptr, const std::nothrow_t&) noexcept { ::operator delete[](ptr); } 134 135 _LIBCPP_WEAK void operator delete[](void* ptr, size_t) noexcept { ::operator delete[](ptr); } 136 137 #if _LIBCPP_HAS_LIBRARY_ALIGNED_ALLOCATION 138 139 static void* operator_new_aligned_impl(std::size_t size, std::align_val_t alignment) { 140 if (size == 0) 141 size = 1; 142 if (static_cast<size_t>(alignment) < sizeof(void*)) 143 alignment = std::align_val_t(sizeof(void*)); 144 145 // Try allocating memory. If allocation fails and there is a new_handler, 146 // call it to try free up memory, and try again until it succeeds, or until 147 // the new_handler decides to terminate. 148 void* p; 149 while ((p = std::__libcpp_aligned_alloc(static_cast<std::size_t>(alignment), size)) == nullptr) { 150 std::new_handler nh = std::get_new_handler(); 151 if (nh) 152 nh(); 153 else 154 break; 155 } 156 return p; 157 } 158 159 _LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void* 160 operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC { 161 void* p = operator_new_aligned_impl(size, alignment); 162 if (p == nullptr) 163 __throw_bad_alloc_shim(); 164 return p; 165 } 166 167 _LIBCPP_WEAK void* operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept { 168 # if !_LIBCPP_HAS_EXCEPTIONS 169 # if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION 170 _LIBCPP_ASSERT_SHIM( 171 !std::__is_function_overridden(static_cast<void* (*)(std::size_t, std::align_val_t)>(&operator new)), 172 "libc++ was configured with exceptions disabled and `operator new(size_t, align_val_t)` has been overridden, " 173 "but `operator new(size_t, align_val_t, nothrow_t)` has not been overridden. This is problematic because " 174 "`operator new(size_t, align_val_t, nothrow_t)` must call `operator new(size_t, align_val_t)`, which will " 175 "terminate in case it fails to allocate, making it impossible for `operator new(size_t, align_val_t, nothrow_t)` " 176 "to fulfill its contract (since it should return nullptr upon failure). Please make sure you override " 177 "`operator new(size_t, align_val_t, nothrow_t)` as well."); 178 # endif 179 180 return operator_new_aligned_impl(size, alignment); 181 # else 182 void* p = nullptr; 183 try { 184 p = ::operator new(size, alignment); 185 } catch (...) { 186 } 187 return p; 188 # endif 189 } 190 191 _LIBCPP_MAKE_OVERRIDABLE_FUNCTION_DETECTABLE _LIBCPP_WEAK void* 192 operator new[](size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC { 193 return ::operator new(size, alignment); 194 } 195 196 _LIBCPP_WEAK void* operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) noexcept { 197 # if !_LIBCPP_HAS_EXCEPTIONS 198 # if _LIBCPP_CAN_DETECT_OVERRIDDEN_FUNCTION 199 _LIBCPP_ASSERT_SHIM( 200 !std::__is_function_overridden(static_cast<void* (*)(std::size_t, std::align_val_t)>(&operator new[])), 201 "libc++ was configured with exceptions disabled and `operator new[](size_t, align_val_t)` has been overridden, " 202 "but `operator new[](size_t, align_val_t, nothrow_t)` has not been overridden. This is problematic because " 203 "`operator new[](size_t, align_val_t, nothrow_t)` must call `operator new[](size_t, align_val_t)`, which will " 204 "terminate in case it fails to allocate, making it impossible for `operator new[](size_t, align_val_t, " 205 "nothrow_t)` to fulfill its contract (since it should return nullptr upon failure). Please make sure you " 206 "override " 207 "`operator new[](size_t, align_val_t, nothrow_t)` as well."); 208 # endif 209 210 return operator_new_aligned_impl(size, alignment); 211 # else 212 void* p = nullptr; 213 try { 214 p = ::operator new[](size, alignment); 215 } catch (...) { 216 } 217 return p; 218 # endif 219 } 220 221 _LIBCPP_WEAK void operator delete(void* ptr, std::align_val_t) noexcept { std::__libcpp_aligned_free(ptr); } 222 223 _LIBCPP_WEAK void operator delete(void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept { 224 ::operator delete(ptr, alignment); 225 } 226 227 _LIBCPP_WEAK void operator delete(void* ptr, size_t, std::align_val_t alignment) noexcept { 228 ::operator delete(ptr, alignment); 229 } 230 231 _LIBCPP_WEAK void operator delete[](void* ptr, std::align_val_t alignment) noexcept { 232 ::operator delete(ptr, alignment); 233 } 234 235 _LIBCPP_WEAK void operator delete[](void* ptr, std::align_val_t alignment, const std::nothrow_t&) noexcept { 236 ::operator delete[](ptr, alignment); 237 } 238 239 _LIBCPP_WEAK void operator delete[](void* ptr, size_t, std::align_val_t alignment) noexcept { 240 ::operator delete[](ptr, alignment); 241 } 242 243 #endif // _LIBCPP_HAS_LIBRARY_ALIGNED_ALLOCATION 244 // ------------------ END COPY ------------------ 245