libcxxabi: upgrade from llvm 10 to 11rc1

This commit is contained in:
Andrew Kelley 2020-08-04 17:30:57 -07:00
parent 54b67c2025
commit 42da1d385d
11 changed files with 406 additions and 134 deletions

View File

@ -76,4 +76,12 @@
# define _LIBCXXABI_GUARD_ABI_ARM
#endif
#if defined(_LIBCXXABI_COMPILER_CLANG)
# if !__has_feature(cxx_exceptions)
# define _LIBCXXABI_NO_EXCEPTIONS
# endif
#elif defined(_LIBCXXABI_COMPILER_GCC) && !__EXCEPTIONS
# define _LIBCXXABI_NO_EXCEPTIONS
#endif
#endif // ____CXXABI_CONFIG_H

View File

@ -12,52 +12,54 @@
#include "abort_message.h"
#ifdef __BIONIC__
#include <android/api-level.h>
#if __ANDROID_API__ >= 21
#include <syslog.h>
extern "C" void android_set_abort_message(const char* msg);
#else
#include <assert.h>
#endif // __ANDROID_API__ >= 21
# include <android/api-level.h>
# if __ANDROID_API__ >= 21
# include <syslog.h>
extern "C" void android_set_abort_message(const char* msg);
# else
# include <assert.h>
# endif // __ANDROID_API__ >= 21
#endif // __BIONIC__
#ifdef __APPLE__
# if defined(__has_include) && __has_include(<CrashReporterClient.h>)
# define HAVE_CRASHREPORTERCLIENT_H
# include <CrashReporterClient.h>
# endif
#if defined(__APPLE__) && __has_include(<CrashReporterClient.h>)
# include <CrashReporterClient.h>
# define _LIBCXXABI_USE_CRASHREPORTER_CLIENT
#endif
void abort_message(const char* format, ...)
{
// write message to stderr
// Write message to stderr. We do this before formatting into a
// variable-size buffer so that we still get some information if
// formatting into the variable-sized buffer fails.
#if !defined(NDEBUG) || !defined(LIBCXXABI_BAREMETAL)
#ifdef __APPLE__
fprintf(stderr, "libc++abi.dylib: ");
#endif
va_list list;
va_start(list, format);
vfprintf(stderr, format, list);
va_end(list);
fprintf(stderr, "\n");
{
fprintf(stderr, "libc++abi: ");
va_list list;
va_start(list, format);
vfprintf(stderr, format, list);
va_end(list);
fprintf(stderr, "\n");
}
#endif
#if defined(__APPLE__) && defined(HAVE_CRASHREPORTERCLIENT_H)
// record message in crash report
// Format the arguments into an allocated buffer. We leak the buffer on
// purpose, since we're about to abort() anyway.
#if defined(_LIBCXXABI_USE_CRASHREPORTER_CLIENT)
char* buffer;
va_list list2;
va_start(list2, format);
vasprintf(&buffer, format, list2);
va_end(list2);
va_list list;
va_start(list, format);
vasprintf(&buffer, format, list);
va_end(list);
CRSetCrashLogMessage(buffer);
#elif defined(__BIONIC__)
char* buffer;
va_list list2;
va_start(list2, format);
vasprintf(&buffer, format, list2);
va_end(list2);
va_list list;
va_start(list, format);
vasprintf(&buffer, format, list);
va_end(list);
#if __ANDROID_API__ >= 21
# if __ANDROID_API__ >= 21
// Show error in tombstone.
android_set_abort_message(buffer);
@ -65,12 +67,12 @@ void abort_message(const char* format, ...)
openlog("libc++abi", 0, 0);
syslog(LOG_CRIT, "%s", buffer);
closelog();
#else
# else
// The good error reporting wasn't available in Android until L. Since we're
// about to abort anyway, just call __assert2, which will log _somewhere_
// (tombstone and/or logcat) in older releases.
__assert2(__FILE__, __LINE__, __func__, buffer);
#endif // __ANDROID_API__ >= 21
# endif // __ANDROID_API__ >= 21
#endif // __BIONIC__
abort();

View File

@ -11,16 +11,7 @@
#include "cxxabi.h"
#ifdef __cplusplus
extern "C" {
#endif
_LIBCXXABI_HIDDEN _LIBCXXABI_NORETURN void
extern "C" _LIBCXXABI_HIDDEN _LIBCXXABI_NORETURN void
abort_message(const char *format, ...) __attribute__((format(printf, 1, 2)));
#ifdef __cplusplus
}
#endif
#endif

View File

@ -40,7 +40,6 @@
#include "__cxxabi_config.h"
#include "include/atomic_support.h"
#include <unistd.h>
#include <sys/types.h>
#if defined(__has_include)
# if __has_include(<sys/syscall.h>)
# include <sys/syscall.h>
@ -108,6 +107,32 @@ struct LazyValue {
bool is_init = false;
};
template <class IntType>
class AtomicInt {
public:
using MemoryOrder = std::__libcpp_atomic_order;
explicit AtomicInt(IntType *b) : b(b) {}
AtomicInt(AtomicInt const&) = delete;
AtomicInt& operator=(AtomicInt const&) = delete;
IntType load(MemoryOrder ord) {
return std::__libcpp_atomic_load(b, ord);
}
void store(IntType val, MemoryOrder ord) {
std::__libcpp_atomic_store(b, val, ord);
}
IntType exchange(IntType new_val, MemoryOrder ord) {
return std::__libcpp_atomic_exchange(b, new_val, ord);
}
bool compare_exchange(IntType *expected, IntType desired, MemoryOrder ord_success, MemoryOrder ord_failure) {
return std::__libcpp_atomic_compare_exchange(b, expected, desired, ord_success, ord_failure);
}
private:
IntType *b;
};
//===----------------------------------------------------------------------===//
// PlatformGetThreadID
//===----------------------------------------------------------------------===//
@ -195,7 +220,7 @@ public:
public:
/// base_address - the address of the original guard object.
void* const base_address;
/// The address of the guord byte at offset 0.
/// The address of the guard byte at offset 0.
uint8_t* const guard_byte_address;
/// The address of the byte used by the implementation during initialization.
uint8_t* const init_byte_address;

View File

@ -12,7 +12,7 @@
#ifndef _CXA_HANDLERS_H
#define _CXA_HANDLERS_H
#include <__cxxabi_config.h>
#include "__cxxabi_config.h"
#include <exception>

View File

@ -1,22 +0,0 @@
//===------------------------- cxa_unexpected.cpp -------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include <exception>
#include "cxxabi.h"
#include "cxa_exception.h"
namespace __cxxabiv1
{
extern "C"
{
}
} // namespace __cxxabiv1

View File

@ -24,9 +24,9 @@
namespace __cxxabiv1 {
#if 0
#pragma mark --Helper routines and classes --
#endif
//
// Helper routines and classes
//
namespace {
inline static size_t __get_element_count ( void *p ) {
@ -111,9 +111,9 @@ namespace {
};
}
#if 0
#pragma mark --Externally visible routines--
#endif
//
// Externally visible routines
//
namespace {
_LIBCXXABI_NORETURN

View File

@ -98,7 +98,7 @@
X(BoolExpr) \
X(StringLiteral) \
X(LambdaExpr) \
X(IntegerCastExpr) \
X(EnumLiteral) \
X(IntegerLiteral) \
X(FloatLiteral) \
X(DoubleLiteral) \
@ -2036,22 +2036,26 @@ public:
}
};
class IntegerCastExpr : public Node {
class EnumLiteral : public Node {
// ty(integer)
const Node *Ty;
StringView Integer;
public:
IntegerCastExpr(const Node *Ty_, StringView Integer_)
: Node(KIntegerCastExpr), Ty(Ty_), Integer(Integer_) {}
EnumLiteral(const Node *Ty_, StringView Integer_)
: Node(KEnumLiteral), Ty(Ty_), Integer(Integer_) {}
template<typename Fn> void match(Fn F) const { F(Ty, Integer); }
void printLeft(OutputStream &S) const override {
S += "(";
S << "(";
Ty->print(S);
S += ")";
S += Integer;
S << ")";
if (Integer[0] == 'n')
S << "-" << Integer.dropFront(1);
else
S << Integer;
}
};
@ -4064,8 +4068,11 @@ Qualifiers AbstractManglingParser<Alloc, Derived>::parseCVQualifiers() {
// ::= fp <top-level CV-Qualifiers> <parameter-2 non-negative number> _ # L == 0, second and later parameters
// ::= fL <L-1 non-negative number> p <top-level CV-Qualifiers> _ # L > 0, first parameter
// ::= fL <L-1 non-negative number> p <top-level CV-Qualifiers> <parameter-2 non-negative number> _ # L > 0, second and later parameters
// ::= fpT # 'this' expression (not part of standard?)
template <typename Derived, typename Alloc>
Node *AbstractManglingParser<Derived, Alloc>::parseFunctionParam() {
if (consumeIf("fpT"))
return make<NameType>("this");
if (consumeIf("fp")) {
parseCVQualifiers();
StringView Num = parseNumber();
@ -4225,7 +4232,13 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExprPrimary() {
return getDerived().template parseFloatingLiteral<double>();
case 'e':
++First;
#if defined(__powerpc__) || defined(__s390__)
// Handle cases where long doubles encoded with e have the same size
// and representation as doubles.
return getDerived().template parseFloatingLiteral<double>();
#else
return getDerived().template parseFloatingLiteral<long double>();
#endif
case '_':
if (consumeIf("_Z")) {
Node *R = getDerived().parseEncoding();
@ -4264,12 +4277,12 @@ Node *AbstractManglingParser<Derived, Alloc>::parseExprPrimary() {
Node *T = getDerived().parseType();
if (T == nullptr)
return nullptr;
StringView N = parseNumber();
StringView N = parseNumber(/*AllowNegative=*/true);
if (N.empty())
return nullptr;
if (!consumeIf('E'))
return nullptr;
return make<IntegerCastExpr>(T, N);
return make<EnumLiteral>(T, N);
}
}
}
@ -5083,6 +5096,22 @@ Node *AbstractManglingParser<Derived, Alloc>::parseSpecialName() {
// ::= <special-name>
template <typename Derived, typename Alloc>
Node *AbstractManglingParser<Derived, Alloc>::parseEncoding() {
// The template parameters of an encoding are unrelated to those of the
// enclosing context.
class SaveTemplateParams {
AbstractManglingParser *Parser;
decltype(TemplateParams) OldParams;
public:
SaveTemplateParams(AbstractManglingParser *Parser) : Parser(Parser) {
OldParams = std::move(Parser->TemplateParams);
Parser->TemplateParams.clear();
}
~SaveTemplateParams() {
Parser->TemplateParams = std::move(OldParams);
}
} SaveTemplateParams(this);
if (look() == 'G' || look() == 'T')
return getDerived().parseSpecialName();

View File

@ -177,34 +177,4 @@ bool __libcpp_atomic_compare_exchange(_ValueType* __val,
_LIBCPP_END_NAMESPACE_STD
namespace {
template <class IntType>
class AtomicInt {
public:
using MemoryOrder = std::__libcpp_atomic_order;
explicit AtomicInt(IntType *b) : b(b) {}
AtomicInt(AtomicInt const&) = delete;
AtomicInt& operator=(AtomicInt const&) = delete;
IntType load(MemoryOrder ord) {
return std::__libcpp_atomic_load(b, ord);
}
void store(IntType val, MemoryOrder ord) {
std::__libcpp_atomic_store(b, val, ord);
}
IntType exchange(IntType new_val, MemoryOrder ord) {
return std::__libcpp_atomic_exchange(b, new_val, ord);
}
bool compare_exchange(IntType *expected, IntType desired, MemoryOrder ord_success, MemoryOrder ord_failure) {
return std::__libcpp_atomic_compare_exchange(b, expected, desired, ord_success, ord_failure);
}
private:
IntType *b;
};
} // end namespace
#endif // ATOMIC_SUPPORT_H

View File

@ -8,11 +8,11 @@
#include "private_typeinfo.h"
// The flag _LIBCXX_DYNAMIC_FALLBACK is used to make dynamic_cast more
// forgiving when type_info's mistakenly have hidden visibility and thus
// multiple type_infos can exist for a single type.
// The flag _LIBCXXABI_FORGIVING_DYNAMIC_CAST is used to make dynamic_cast
// more forgiving when type_info's mistakenly have hidden visibility and
// thus multiple type_infos can exist for a single type.
//
// When _LIBCXX_DYNAMIC_FALLBACK is defined, and only in the case where
// When _LIBCXXABI_FORGIVING_DYNAMIC_CAST is defined, and only in the case where
// there is a detected inconsistency in the type_info hierarchy during a
// dynamic_cast, then the equality operation will fall back to using strcmp
// on type_info names to determine type_info equality.
@ -23,7 +23,7 @@
// algorithm and an inconsistency is still detected, dynamic_cast will call
// abort with an appropriate message.
//
// The current implementation of _LIBCXX_DYNAMIC_FALLBACK requires a
// The current implementation of _LIBCXXABI_FORGIVING_DYNAMIC_CAST requires a
// printf-like function called syslog:
//
// void syslog(int facility_priority, const char* format, ...);
@ -31,21 +31,22 @@
// If you want this functionality but your platform doesn't have syslog,
// just implement it in terms of fprintf(stderr, ...).
//
// _LIBCXX_DYNAMIC_FALLBACK is currently off by default.
// _LIBCXXABI_FORGIVING_DYNAMIC_CAST is currently off by default.
// On Windows, typeids are different between DLLs and EXEs, so comparing
// type_info* will work for typeids from the same compiled file but fail
// for typeids from a DLL and an executable. Among other things, exceptions
// are not caught by handlers since can_catch() returns false.
//
// Defining _LIBCXX_DYNAMIC_FALLBACK does not help since can_catch() calls
// Defining _LIBCXXABI_FORGIVING_DYNAMIC_CAST does not help since can_catch() calls
// is_equal() with use_strcmp=false so the string names are not compared.
#include <string.h>
#ifdef _LIBCXX_DYNAMIC_FALLBACK
#ifdef _LIBCXXABI_FORGIVING_DYNAMIC_CAST
#include "abort_message.h"
#include <sys/syslog.h>
#include <atomic>
#endif
static inline
@ -633,22 +634,25 @@ __dynamic_cast(const void *static_ptr, const __class_type_info *static_type,
info.number_of_dst_type = 1;
// Do the search
dynamic_type->search_above_dst(&info, dynamic_ptr, dynamic_ptr, public_path, false);
#ifdef _LIBCXX_DYNAMIC_FALLBACK
#ifdef _LIBCXXABI_FORGIVING_DYNAMIC_CAST
// The following if should always be false because we should definitely
// find (static_ptr, static_type), either on a public or private path
if (info.path_dst_ptr_to_static_ptr == unknown)
{
// We get here only if there is some kind of visibility problem
// in client code.
syslog(LOG_ERR, "dynamic_cast error 1: Both of the following type_info's "
"should have public visibility. At least one of them is hidden. %s"
", %s.\n", static_type->name(), dynamic_type->name());
static std::atomic<size_t> error_count(0);
size_t error_count_snapshot = error_count.fetch_add(1, std::memory_order_relaxed);
if ((error_count_snapshot & (error_count_snapshot-1)) == 0)
syslog(LOG_ERR, "dynamic_cast error 1: Both of the following type_info's "
"should have public visibility. At least one of them is hidden. %s"
", %s.\n", static_type->name(), dynamic_type->name());
// Redo the search comparing type_info's using strcmp
info = {dst_type, static_ptr, static_type, src2dst_offset, 0};
info.number_of_dst_type = 1;
dynamic_type->search_above_dst(&info, dynamic_ptr, dynamic_ptr, public_path, true);
}
#endif // _LIBCXX_DYNAMIC_FALLBACK
#endif // _LIBCXXABI_FORGIVING_DYNAMIC_CAST
// Query the search.
if (info.path_dst_ptr_to_static_ptr == public_path)
dst_ptr = dynamic_ptr;
@ -657,22 +661,25 @@ __dynamic_cast(const void *static_ptr, const __class_type_info *static_type,
{
// Not using giant short cut. Do the search
dynamic_type->search_below_dst(&info, dynamic_ptr, public_path, false);
#ifdef _LIBCXX_DYNAMIC_FALLBACK
#ifdef _LIBCXXABI_FORGIVING_DYNAMIC_CAST
// The following if should always be false because we should definitely
// find (static_ptr, static_type), either on a public or private path
if (info.path_dst_ptr_to_static_ptr == unknown &&
info.path_dynamic_ptr_to_static_ptr == unknown)
{
syslog(LOG_ERR, "dynamic_cast error 2: One or more of the following type_info's "
"has hidden visibility or is defined in more than one translation "
"unit. They should all have public visibility. "
"%s, %s, %s.\n", static_type->name(), dynamic_type->name(),
dst_type->name());
static std::atomic<size_t> error_count(0);
size_t error_count_snapshot = error_count.fetch_add(1, std::memory_order_relaxed);
if ((error_count_snapshot & (error_count_snapshot-1)) == 0)
syslog(LOG_ERR, "dynamic_cast error 2: One or more of the following type_info's "
"has hidden visibility or is defined in more than one translation "
"unit. They should all have public visibility. "
"%s, %s, %s.\n", static_type->name(), dynamic_type->name(),
dst_type->name());
// Redo the search comparing type_info's using strcmp
info = {dst_type, static_ptr, static_type, src2dst_offset, 0};
dynamic_type->search_below_dst(&info, dynamic_ptr, public_path, true);
}
#endif // _LIBCXX_DYNAMIC_FALLBACK
#endif // _LIBCXXABI_FORGIVING_DYNAMIC_CAST
// Query the search.
switch (info.number_to_static_ptr)
{

View File

@ -0,0 +1,262 @@
//===--------------------- stdlib_new_delete.cpp --------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//
// This file implements the new and delete operators.
//===----------------------------------------------------------------------===//
#define _LIBCPP_BUILDING_LIBRARY
#include "__cxxabi_config.h"
#include <new>
#include <cstdlib>
#if !defined(_THROW_BAD_ALLOC) || !defined(_NOEXCEPT) || !defined(_LIBCXXABI_WEAK)
#error The _THROW_BAD_ALLOC, _NOEXCEPT, and _LIBCXXABI_WEAK libc++ macros must \
already be defined by libc++.
#endif
// Implement all new and delete operators as weak definitions
// in this shared library, so that they can be overridden by programs
// that define non-weak copies of the functions.
_LIBCXXABI_WEAK
void *
operator new(std::size_t size) _THROW_BAD_ALLOC
{
if (size == 0)
size = 1;
void* p;
while ((p = ::malloc(size)) == 0)
{
// If malloc fails and there is a new_handler,
// call it to try free up memory.
std::new_handler nh = std::get_new_handler();
if (nh)
nh();
else
#ifndef _LIBCXXABI_NO_EXCEPTIONS
throw std::bad_alloc();
#else
break;
#endif
}
return p;
}
_LIBCXXABI_WEAK
void*
operator new(size_t size, const std::nothrow_t&) _NOEXCEPT
{
void* p = 0;
#ifndef _LIBCXXABI_NO_EXCEPTIONS
try
{
#endif // _LIBCXXABI_NO_EXCEPTIONS
p = ::operator new(size);
#ifndef _LIBCXXABI_NO_EXCEPTIONS
}
catch (...)
{
}
#endif // _LIBCXXABI_NO_EXCEPTIONS
return p;
}
_LIBCXXABI_WEAK
void*
operator new[](size_t size) _THROW_BAD_ALLOC
{
return ::operator new(size);
}
_LIBCXXABI_WEAK
void*
operator new[](size_t size, const std::nothrow_t&) _NOEXCEPT
{
void* p = 0;
#ifndef _LIBCXXABI_NO_EXCEPTIONS
try
{
#endif // _LIBCXXABI_NO_EXCEPTIONS
p = ::operator new[](size);
#ifndef _LIBCXXABI_NO_EXCEPTIONS
}
catch (...)
{
}
#endif // _LIBCXXABI_NO_EXCEPTIONS
return p;
}
_LIBCXXABI_WEAK
void
operator delete(void* ptr) _NOEXCEPT
{
if (ptr)
::free(ptr);
}
_LIBCXXABI_WEAK
void
operator delete(void* ptr, const std::nothrow_t&) _NOEXCEPT
{
::operator delete(ptr);
}
_LIBCXXABI_WEAK
void
operator delete(void* ptr, size_t) _NOEXCEPT
{
::operator delete(ptr);
}
_LIBCXXABI_WEAK
void
operator delete[] (void* ptr) _NOEXCEPT
{
::operator delete(ptr);
}
_LIBCXXABI_WEAK
void
operator delete[] (void* ptr, const std::nothrow_t&) _NOEXCEPT
{
::operator delete[](ptr);
}
_LIBCXXABI_WEAK
void
operator delete[] (void* ptr, size_t) _NOEXCEPT
{
::operator delete[](ptr);
}
#if !defined(_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION)
_LIBCXXABI_WEAK
void *
operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC
{
if (size == 0)
size = 1;
if (static_cast<size_t>(alignment) < sizeof(void*))
alignment = std::align_val_t(sizeof(void*));
void* p;
#if defined(_LIBCPP_WIN32API)
while ((p = _aligned_malloc(size, static_cast<size_t>(alignment))) == nullptr)
#else
while (::posix_memalign(&p, static_cast<size_t>(alignment), size) != 0)
#endif
{
// If posix_memalign fails and there is a new_handler,
// call it to try free up memory.
std::new_handler nh = std::get_new_handler();
if (nh)
nh();
else {
#ifndef _LIBCXXABI_NO_EXCEPTIONS
throw std::bad_alloc();
#else
p = nullptr; // posix_memalign doesn't initialize 'p' on failure
break;
#endif
}
}
return p;
}
_LIBCXXABI_WEAK
void*
operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT
{
void* p = 0;
#ifndef _LIBCXXABI_NO_EXCEPTIONS
try
{
#endif // _LIBCXXABI_NO_EXCEPTIONS
p = ::operator new(size, alignment);
#ifndef _LIBCXXABI_NO_EXCEPTIONS
}
catch (...)
{
}
#endif // _LIBCXXABI_NO_EXCEPTIONS
return p;
}
_LIBCXXABI_WEAK
void*
operator new[](size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC
{
return ::operator new(size, alignment);
}
_LIBCXXABI_WEAK
void*
operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT
{
void* p = 0;
#ifndef _LIBCXXABI_NO_EXCEPTIONS
try
{
#endif // _LIBCXXABI_NO_EXCEPTIONS
p = ::operator new[](size, alignment);
#ifndef _LIBCXXABI_NO_EXCEPTIONS
}
catch (...)
{
}
#endif // _LIBCXXABI_NO_EXCEPTIONS
return p;
}
_LIBCXXABI_WEAK
void
operator delete(void* ptr, std::align_val_t) _NOEXCEPT
{
if (ptr)
#if defined(_LIBCPP_WIN32API)
::_aligned_free(ptr);
#else
::free(ptr);
#endif
}
_LIBCXXABI_WEAK
void
operator delete(void* ptr, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT
{
::operator delete(ptr, alignment);
}
_LIBCXXABI_WEAK
void
operator delete(void* ptr, size_t, std::align_val_t alignment) _NOEXCEPT
{
::operator delete(ptr, alignment);
}
_LIBCXXABI_WEAK
void
operator delete[] (void* ptr, std::align_val_t alignment) _NOEXCEPT
{
::operator delete(ptr, alignment);
}
_LIBCXXABI_WEAK
void
operator delete[] (void* ptr, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT
{
::operator delete[](ptr, alignment);
}
_LIBCXXABI_WEAK
void
operator delete[] (void* ptr, size_t, std::align_val_t alignment) _NOEXCEPT
{
::operator delete[](ptr, alignment);
}
#endif // !_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION