extern "C" void* chk_memalign(size_t alignment, size_t bytes) { if (DebugCallsDisabled()) { return g_malloc_dispatch->memalign(alignment, bytes); } if (alignment <= MALLOC_ALIGNMENT) { return chk_malloc(bytes); } // Make the alignment a power of two. if (!powerof2(alignment)) { alignment = BIONIC_ROUND_UP_POWER_OF_2(alignment); } // here, alignment is at least MALLOC_ALIGNMENT<<1 bytes // we will align by at least MALLOC_ALIGNMENT bytes // and at most alignment-MALLOC_ALIGNMENT bytes size_t size = (alignment-MALLOC_ALIGNMENT) + bytes; if (size < bytes) { // Overflow. return NULL; } void* base = g_malloc_dispatch->malloc(sizeof(hdr_t) + size + sizeof(ftr_t)); if (base != NULL) { // Check that the actual pointer that will be returned is aligned // properly. uintptr_t ptr = reinterpret_cast<uintptr_t>(user(reinterpret_cast<hdr_t*>(base))); if ((ptr % alignment) != 0) { // Align the pointer. ptr += ((-ptr) % alignment); } hdr_t* hdr = meta(reinterpret_cast<void*>(ptr)); hdr->base = base; hdr->bt_depth = GET_BACKTRACE(hdr->bt, MAX_BACKTRACE_DEPTH); add(hdr, bytes); return user(hdr); } return base; }
void* debug_memalign(size_t alignment, size_t bytes) { if (DebugCallsDisabled()) { return g_dispatch->memalign(alignment, bytes); } ScopedDisableDebugCalls disable; if (bytes == 0) { bytes = 1; } void* pointer; if (g_debug->need_header()) { if (bytes > Header::max_size()) { errno = ENOMEM; return nullptr; } // Make the alignment a power of two. if (!powerof2(alignment)) { alignment = BIONIC_ROUND_UP_POWER_OF_2(alignment); } // Force the alignment to at least MINIMUM_ALIGNMENT_BYTES to guarantee // that the header is aligned properly. if (alignment < MINIMUM_ALIGNMENT_BYTES) { alignment = MINIMUM_ALIGNMENT_BYTES; } // We don't have any idea what the natural alignment of // the underlying native allocator is, so we always need to // over allocate. size_t real_size = alignment + bytes + g_debug->extra_bytes(); if (real_size < bytes) { // Overflow. errno = ENOMEM; return nullptr; } pointer = g_dispatch->malloc(real_size); if (pointer == nullptr) { return nullptr; } uintptr_t value = reinterpret_cast<uintptr_t>(pointer) + g_debug->pointer_offset(); // Now align the pointer. value += (-value % alignment); Header* header = g_debug->GetHeader(reinterpret_cast<void*>(value)); pointer = InitHeader(header, pointer, bytes); } else { size_t real_size = bytes + g_debug->extra_bytes(); if (real_size < bytes) { // Overflow. errno = ENOMEM; return nullptr; } pointer = g_dispatch->memalign(alignment, real_size); } if (pointer != nullptr && g_debug->config().options & FILL_ON_ALLOC) { size_t bytes = internal_malloc_usable_size(pointer); size_t fill_bytes = g_debug->config().fill_on_alloc_bytes; bytes = (bytes < fill_bytes) ? bytes : fill_bytes; memset(pointer, g_debug->config().fill_alloc_value, bytes); } return pointer; }