blob: 569c1a19cfc7c2a901ea45cb97d5980d4be5c01a [file] [log] [blame]
// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <new>
// Placement new operators are inlined in the <new> header.
// No linkage definitions are required.
#include <stdlib.h>
#include <zircon/assert.h>
// In ASan builds, the ASan runtime supplies the operator new/delete functions.
// Those versions check for mismatches between allocation entry path and
// deallocation entry path, so we don't want to override them. Also, in
// certain complex static linking situations, it's difficult to avoid sometimes
// getting the definition of one from this library and another from libc++.
#if !__has_feature(address_sanitizer)
#if !_KERNEL
static inline size_t round_up_to_alignment(size_t s, std::align_val_t align) {
return (s + static_cast<size_t>(align) - 1) & ~(static_cast<size_t>(align) - 1);
}
// The kernel does not want non-AllocCheckered non-placement new
// overloads, but userspace can have them.
void* operator new(size_t s) {
if (s == 0u) {
s = 1u;
}
auto mem = ::malloc(s);
if (!mem) {
ZX_PANIC("Out of memory (new)\n");
}
return mem;
}
void* operator new(size_t s, std::align_val_t align) {
if (s == 0u) {
s = 1u;
}
s = round_up_to_alignment(s, align);
auto mem = aligned_alloc(static_cast<size_t>(align), s);
if (!mem) {
ZX_PANIC("Out of memory (new)\n");
}
return mem;
}
void* operator new[](size_t s) {
if (s == 0u) {
s = 1u;
}
auto mem = ::malloc(s);
if (!mem) {
ZX_PANIC("Out of memory (new[])\n");
}
return mem;
}
void* operator new[](size_t s, std::align_val_t align) {
if (s == 0u) {
s = 1u;
}
s = round_up_to_alignment(s, align);
auto mem = aligned_alloc(static_cast<size_t>(align), s);
if (!mem) {
ZX_PANIC("Out of memory (new[])\n");
}
return mem;
}
void* operator new(size_t s, const std::nothrow_t&) noexcept {
if (s == 0u) {
s = 1u;
}
return ::malloc(s);
}
void* operator new(size_t s, std::align_val_t align, const std::nothrow_t&) noexcept {
if (s == 0u) {
s = 1u;
}
s = round_up_to_alignment(s, align);
return aligned_alloc(static_cast<size_t>(align), s);
}
void* operator new[](size_t s, const std::nothrow_t&) noexcept {
if (s == 0u) {
s = 1u;
}
return ::malloc(s);
}
void* operator new[](size_t s, std::align_val_t align, const std::nothrow_t&) noexcept {
if (s == 0u) {
s = 1u;
}
s = round_up_to_alignment(s, align);
return aligned_alloc(static_cast<size_t>(align), s);
}
#else // _KERNEL
static_assert(HEAP_DEFAULT_ALIGNMENT >= __STDCPP_DEFAULT_NEW_ALIGNMENT__);
// kernel versions may pass through the call site to the underlying allocator
void* operator new(size_t s, void* caller, const std::nothrow_t&) noexcept {
if (s == 0u) {
s = 1u;
}
return ::malloc_debug_caller(s, caller);
}
void* operator new(size_t s, std::align_val_t align, void* caller, const std::nothrow_t&) noexcept {
if (s == 0u) {
s = 1u;
}
return ::memalign_debug_caller(s, static_cast<size_t>(align), caller);
}
void* operator new[](size_t s, void* caller, const std::nothrow_t&) noexcept {
if (s == 0u) {
s = 1u;
}
return ::malloc_debug_caller(s, caller);
}
void* operator new[](size_t s, std::align_val_t align, void* caller, const std::nothrow_t&) noexcept {
if (s == 0u) {
s = 1u;
}
return ::memalign_debug_caller(s, static_cast<size_t>(align), caller);
}
#endif // _KERNEL
void operator delete(void* p) {
return ::free(p);
}
void operator delete[](void* p) {
return ::free(p);
}
void operator delete(void* p, size_t s) {
return ::free(p);
}
void operator delete[](void* p, size_t s) {
return ::free(p);
}
void operator delete(void* p, std::align_val_t align) {
return ::free(p);
}
void operator delete(void* p, std::size_t s, std::align_val_t align) {
return ::free(p);
}
#endif // !__has_feature(address_sanitizer)
// These are the mangled names of all the functions above. Because these
// functions are magical in the language, the compiler insists on making
// default-visibility definitions regardless of all the ways to tell it to use
// hidden visibility. So there is nothing left but to go around the compiler's
// back and force them to .hidden via assembler directives. These declarations
// have no effect and do no harm when not all of these functions are defined
// here (kernel, ASan).
asm(".hidden _ZdaPv");
asm(".hidden _ZdaPvm");
asm(".hidden _ZdlPv");
asm(".hidden _ZdlPvm");
asm(".hidden _ZdlPvSt11align_val_t");
asm(".hidden _ZdlPvmSt11align_val_t");
asm(".hidden _Znam");
asm(".hidden _ZnamPv");
asm(".hidden _ZnamRKSt9nothrow_t");
asm(".hidden _Znwm");
asm(".hidden _ZnwmPv");
asm(".hidden _ZnwmRKSt9nothrow_t");