asan_allocator2.cc revision 7dd282c0c7d3ca32ee94092289bd802e16fe9867
13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//===-- asan_allocator2.cc ------------------------------------------------===//
23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//
33c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//                     The LLVM Compiler Infrastructure
43c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//
53c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// This file is distributed under the University of Illinois Open Source
63c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// License. See LICENSE.TXT for details.
73c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//
83c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//===----------------------------------------------------------------------===//
93c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//
103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// This file is a part of AddressSanitizer, an address sanity checker.
113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//
123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Implementation of ASan's memory allocator, 2-nd version.
133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// This variant uses the allocator from sanitizer_common, i.e. the one shared
143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// with ThreadSanitizer and MemorySanitizer.
153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//
163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Status: under development, not enabled by default yet.
173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//===----------------------------------------------------------------------===//
183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "asan_allocator.h"
193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#if ASAN_ALLOCATOR_VERSION == 2
203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "asan_mapping.h"
223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "asan_report.h"
233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "asan_thread.h"
243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "sanitizer_common/sanitizer_allocator.h"
253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "sanitizer_common/sanitizer_internal_defs.h"
263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "sanitizer_common/sanitizer_list.h"
273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "sanitizer_common/sanitizer_stackdepot.h"
283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "sanitizer_common/sanitizer_quarantine.h"
293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
303c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace __asan {
313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
323c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct AsanMapUnmapCallback {
333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  void OnMap(uptr p, uptr size) const {
343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    PoisonShadow(p, size, kAsanHeapLeftRedzoneMagic);
353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    // Statistics.
363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    AsanStats &thread_stats = GetCurrentThreadStats();
373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    thread_stats.mmaps++;
383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    thread_stats.mmaped += size;
393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  void OnUnmap(uptr p, uptr size) const {
413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    PoisonShadow(p, size, 0);
423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    // We are about to unmap a chunk of user memory.
433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    // Mark the corresponding shadow memory as not needed.
443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    // Since asan's mapping is compacting, the shadow chunk may be
453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    // not page-aligned, so we only flush the page-aligned portion.
463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    uptr page_size = GetPageSizeCached();
473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    uptr shadow_beg = RoundUpTo(MemToShadow(p), page_size);
483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    uptr shadow_end = RoundDownTo(MemToShadow(p + size), page_size);
493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    FlushUnneededShadowMemory(shadow_beg, shadow_end - shadow_beg);
503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    // Statistics.
513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    AsanStats &thread_stats = GetCurrentThreadStats();
523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    thread_stats.munmaps++;
533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    thread_stats.munmaped += size;
543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#if SANITIZER_WORDSIZE == 64
583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#if defined(__powerpc64__)
593c827367444ee418f129b2c238299f49d3264554Jarkko Poyryconst uptr kAllocatorSpace =  0xa0000000000ULL;
603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#else
613c827367444ee418f129b2c238299f49d3264554Jarkko Poyryconst uptr kAllocatorSpace = 0x600000000000ULL;
623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif
633c827367444ee418f129b2c238299f49d3264554Jarkko Poyryconst uptr kAllocatorSize  =  0x40000000000ULL;  // 4T.
643c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytypedef DefaultSizeClassMap SizeClassMap;
653c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytypedef SizeClassAllocator64<kAllocatorSpace, kAllocatorSize, 0 /*metadata*/,
663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    SizeClassMap, AsanMapUnmapCallback> PrimaryAllocator;
673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#elif SANITIZER_WORDSIZE == 32
683c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const u64 kAddressSpaceSize = 1ULL << 32;
693c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytypedef CompactSizeClassMap SizeClassMap;
703c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytypedef SizeClassAllocator32<0, kAddressSpaceSize, 16,
713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  SizeClassMap, AsanMapUnmapCallback> PrimaryAllocator;
723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif
733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
743c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytypedef SizeClassAllocatorLocalCache<PrimaryAllocator> AllocatorCache;
753c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytypedef LargeMmapAllocator<AsanMapUnmapCallback> SecondaryAllocator;
763c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytypedef CombinedAllocator<PrimaryAllocator, AllocatorCache,
773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    SecondaryAllocator> Allocator;
783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// We can not use THREADLOCAL because it is not supported on some of the
803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// platforms we care about (OSX 10.6, Android).
813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// static THREADLOCAL AllocatorCache cache;
823c827367444ee418f129b2c238299f49d3264554Jarkko PoyryAllocatorCache *GetAllocatorCache(AsanThreadLocalMallocStorage *ms) {
833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  CHECK(ms);
843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  CHECK_LE(sizeof(AllocatorCache), sizeof(ms->allocator2_cache));
853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  return reinterpret_cast<AllocatorCache *>(ms->allocator2_cache);
863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
883c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic Allocator allocator;
893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
903c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const uptr kMaxAllowedMallocSize =
913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  FIRST_32_SECOND_64(3UL << 30, 8UL << 30);
923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
933c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const uptr kMaxThreadLocalQuarantine =
943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  FIRST_32_SECOND_64(1 << 18, 1 << 20);
953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Every chunk of memory allocated by this allocator can be in one of 3 states:
973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// CHUNK_AVAILABLE: the chunk is in the free list and ready to be allocated.
983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// CHUNK_ALLOCATED: the chunk is allocated and not yet freed.
993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// CHUNK_QUARANTINE: the chunk was freed and put into quarantine zone.
1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyryenum {
1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  CHUNK_AVAILABLE  = 0,  // 0 is the default value even if we didn't set it.
1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  CHUNK_ALLOCATED  = 2,
1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  CHUNK_QUARANTINE = 3
1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Valid redzone sizes are 16, 32, 64, ... 2048, so we encode them in 3 bits.
1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// We use adaptive redzones: for larger allocation larger redzones are used.
1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic u32 RZLog2Size(u32 rz_log) {
1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  CHECK_LT(rz_log, 8);
1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  return 16 << rz_log;
1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic u32 RZSize2Log(u32 rz_size) {
1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  CHECK_GE(rz_size, 16);
1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  CHECK_LE(rz_size, 2048);
1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  CHECK(IsPowerOfTwo(rz_size));
1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  u32 res = Log2(rz_size) - 4;
1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  CHECK_EQ(rz_size, RZLog2Size(res));
1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  return res;
1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic uptr ComputeRZLog(uptr user_requested_size) {
1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  u32 rz_log =
1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    user_requested_size <= 64        - 16   ? 0 :
1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    user_requested_size <= 128       - 32   ? 1 :
1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    user_requested_size <= 512       - 64   ? 2 :
1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    user_requested_size <= 4096      - 128  ? 3 :
1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    user_requested_size <= (1 << 14) - 256  ? 4 :
1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    user_requested_size <= (1 << 15) - 512  ? 5 :
1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    user_requested_size <= (1 << 16) - 1024 ? 6 : 7;
1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  return Max(rz_log, RZSize2Log(flags()->redzone));
1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// The memory chunk allocated from the underlying allocator looks like this:
1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// L L L L L L H H U U U U U U R R
1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//   L -- left redzone words (0 or more bytes)
1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//   H -- ChunkHeader (16 bytes), which is also a part of the left redzone.
1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//   U -- user memory.
1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//   R -- right redzone (0 or more bytes)
1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// ChunkBase consists of ChunkHeader and other bytes that overlap with user
1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// memory.
1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// If a memory chunk is allocated by memalign and we had to increase the
1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// allocation size to achieve the proper alignment, then we store this magic
1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// value in the first uptr word of the memory block and store the address of
1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// ChunkBase in the next uptr.
1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// M B ? ? ? L L L L L L  H H U U U U U U
1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//   M -- magic value kMemalignMagic
1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry//   B -- address of ChunkHeader pointing to the first 'H'
1503c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const uptr kMemalignMagic = 0xCC6E96B9;
1513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1523c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct ChunkHeader {
1533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // 1-st 8 bytes.
1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  u32 chunk_state       : 8;  // Must be first.
1553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  u32 alloc_tid         : 24;
1563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  u32 free_tid          : 24;
1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  u32 from_memalign     : 1;
1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  u32 alloc_type        : 2;
1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  u32 rz_log            : 3;
1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // 2-nd 8 bytes
1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // This field is used for small sizes. For large sizes it is equal to
1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // SizeClassMap::kMaxSize and the actual size is stored in the
1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // SecondaryAllocator's metadata.
1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  u32 user_requested_size;
1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  u32 alloc_context_id;
1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct ChunkBase : ChunkHeader {
1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // Header2, intersects with user memory.
1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  AsanChunk *next;
1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  u32 free_context_id;
1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const uptr kChunkHeaderSize = sizeof(ChunkHeader);
1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic const uptr kChunkHeader2Size = sizeof(ChunkBase) - kChunkHeaderSize;
1773c827367444ee418f129b2c238299f49d3264554Jarkko PoyryCOMPILER_CHECK(kChunkHeaderSize == 16);
1783c827367444ee418f129b2c238299f49d3264554Jarkko PoyryCOMPILER_CHECK(kChunkHeader2Size <= 16);
1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct AsanChunk: ChunkBase {
1813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  uptr Beg() { return reinterpret_cast<uptr>(this) + kChunkHeaderSize; }
1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  uptr UsedSize() {
1833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    if (user_requested_size != SizeClassMap::kMaxSize)
1843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      return user_requested_size;
1853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    return *reinterpret_cast<uptr *>(allocator.GetMetaData(AllocBeg()));
1863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  void *AllocBeg() {
1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    if (from_memalign)
1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      return allocator.GetBlockBegin(reinterpret_cast<void *>(this));
1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    return reinterpret_cast<void*>(Beg() - RZLog2Size(rz_log));
1913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
1923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // We store the alloc/free stack traces in the chunk itself.
1933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  u32 *AllocStackBeg() {
1943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    return (u32*)(Beg() - RZLog2Size(rz_log));
1953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
1963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  uptr AllocStackSize() {
1973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    CHECK_LE(RZLog2Size(rz_log), kChunkHeaderSize);
1983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    return (RZLog2Size(rz_log) - kChunkHeaderSize) / sizeof(u32);
1993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
2003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  u32 *FreeStackBeg() {
2013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    return (u32*)(Beg() + kChunkHeader2Size);
2023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
2033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  uptr FreeStackSize() {
2043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    if (user_requested_size < kChunkHeader2Size) return 0;
2053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    uptr available = RoundUpTo(user_requested_size, SHADOW_GRANULARITY);
2063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    return (available - kChunkHeader2Size) / sizeof(u32);
2073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
2083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
2093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2103c827367444ee418f129b2c238299f49d3264554Jarkko Poyryuptr AsanChunkView::Beg() { return chunk_->Beg(); }
2113c827367444ee418f129b2c238299f49d3264554Jarkko Poyryuptr AsanChunkView::End() { return Beg() + UsedSize(); }
2123c827367444ee418f129b2c238299f49d3264554Jarkko Poyryuptr AsanChunkView::UsedSize() { return chunk_->UsedSize(); }
2133c827367444ee418f129b2c238299f49d3264554Jarkko Poyryuptr AsanChunkView::AllocTid() { return chunk_->alloc_tid; }
2143c827367444ee418f129b2c238299f49d3264554Jarkko Poyryuptr AsanChunkView::FreeTid() { return chunk_->free_tid; }
2153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2163c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void GetStackTraceFromId(u32 id, StackTrace *stack) {
2173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  CHECK(id);
2183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  uptr size = 0;
2193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  const uptr *trace = StackDepotGet(id, &size);
2203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  CHECK_LT(size, kStackTraceMax);
2213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  internal_memcpy(stack->trace, trace, sizeof(uptr) * size);
2223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  stack->size = size;
2233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2253c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid AsanChunkView::GetAllocStack(StackTrace *stack) {
2263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (flags()->use_stack_depot)
2273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    GetStackTraceFromId(chunk_->alloc_context_id, stack);
2283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  else
2293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    StackTrace::UncompressStack(stack, chunk_->AllocStackBeg(),
2303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry                                chunk_->AllocStackSize());
2313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2333c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid AsanChunkView::GetFreeStack(StackTrace *stack) {
2343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (flags()->use_stack_depot)
2353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    GetStackTraceFromId(chunk_->free_context_id, stack);
2363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  else
2373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    StackTrace::UncompressStack(stack, chunk_->FreeStackBeg(),
2383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry                                chunk_->FreeStackSize());
2393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2413c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct QuarantineCallback;
2423c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytypedef Quarantine<QuarantineCallback, AsanChunk> AsanQuarantine;
2433c827367444ee418f129b2c238299f49d3264554Jarkko Poyrytypedef AsanQuarantine::Cache QuarantineCache;
2443c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic AsanQuarantine quarantine(LINKER_INITIALIZED);
2453c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic QuarantineCache fallback_quarantine_cache(LINKER_INITIALIZED);
2463c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic AllocatorCache fallback_allocator_cache;
2473c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic SpinMutex fallback_mutex;
2483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2493c827367444ee418f129b2c238299f49d3264554Jarkko PoyryQuarantineCache *GetQuarantineCache(AsanThreadLocalMallocStorage *ms) {
2503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  CHECK(ms);
2513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  CHECK_LE(sizeof(QuarantineCache), sizeof(ms->quarantine_cache));
2523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  return reinterpret_cast<QuarantineCache *>(ms->quarantine_cache);
2533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2553c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystruct QuarantineCallback {
2563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  explicit QuarantineCallback(AllocatorCache *cache)
2573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      : cache_(cache) {
2583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
2593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  void Recycle(AsanChunk *m) {
2613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    CHECK(m->chunk_state == CHUNK_QUARANTINE);
2623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    m->chunk_state = CHUNK_AVAILABLE;
2633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    CHECK_NE(m->alloc_tid, kInvalidTid);
2643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    CHECK_NE(m->free_tid, kInvalidTid);
2653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    PoisonShadow(m->Beg(),
2663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry                 RoundUpTo(m->UsedSize(), SHADOW_GRANULARITY),
2673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry                 kAsanHeapLeftRedzoneMagic);
2683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    void *p = reinterpret_cast<void *>(m->AllocBeg());
2693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    if (m->from_memalign) {
2703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      uptr *memalign_magic = reinterpret_cast<uptr *>(p);
2713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      CHECK_EQ(memalign_magic[0], kMemalignMagic);
2723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      CHECK_EQ(memalign_magic[1], reinterpret_cast<uptr>(m));
2733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    }
2743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    // Statistics.
2763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    AsanStats &thread_stats = GetCurrentThreadStats();
2773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    thread_stats.real_frees++;
2783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    thread_stats.really_freed += m->UsedSize();
2793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    allocator.Deallocate(cache_, p);
2813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
2823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  void *Allocate(uptr size) {
2843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    return allocator.Allocate(cache_, size, 1, false);
2853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
2863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  void Deallocate(void *p) {
2883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    allocator.Deallocate(cache_, p);
2893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
2903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  AllocatorCache *cache_;
2923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
2933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2943c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid InitializeAllocator() {
2953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  allocator.Init();
2963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  quarantine.Init((uptr)flags()->quarantine_size, kMaxThreadLocalQuarantine);
2973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2993c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void *Allocate(uptr size, uptr alignment, StackTrace *stack,
3003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry                      AllocType alloc_type) {
3013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (!asan_inited)
3023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    __asan_init();
3033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  CHECK(stack);
3043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  const uptr min_alignment = SHADOW_GRANULARITY;
3053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (alignment < min_alignment)
3063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    alignment = min_alignment;
3073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (size == 0) {
3083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    // We'd be happy to avoid allocating memory for zero-size requests, but
3093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    // some programs/tests depend on this behavior and assume that malloc would
3103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    // not return NULL even for zero-size allocations. Moreover, it looks like
3113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    // operator new should never return NULL, and results of consecutive "new"
3123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    // calls must be different even if the allocated size is zero.
3133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    size = 1;
3143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
3153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  CHECK(IsPowerOfTwo(alignment));
3163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  uptr rz_log = ComputeRZLog(size);
3173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  uptr rz_size = RZLog2Size(rz_log);
3183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  uptr rounded_size = RoundUpTo(size, alignment);
3193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (rounded_size < kChunkHeader2Size)
3203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    rounded_size = kChunkHeader2Size;
3213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  uptr needed_size = rounded_size + rz_size;
3223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (alignment > min_alignment)
3233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    needed_size += alignment;
3243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  bool using_primary_allocator = true;
3253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // If we are allocating from the secondary allocator, there will be no
3263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // automatic right redzone, so add the right redzone manually.
3273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (!PrimaryAllocator::CanAllocate(needed_size, alignment)) {
3283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    needed_size += rz_size;
3293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    using_primary_allocator = false;
3303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
3313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  CHECK(IsAligned(needed_size, min_alignment));
3323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (size > kMaxAllowedMallocSize || needed_size > kMaxAllowedMallocSize) {
3333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    Report("WARNING: AddressSanitizer failed to allocate %p bytes\n",
3343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry           (void*)size);
3353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    return 0;
3363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
3373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  AsanThread *t = GetCurrentThread();
3393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  void *allocated;
3403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (t) {
3413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    AllocatorCache *cache = GetAllocatorCache(&t->malloc_storage());
3423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    allocated = allocator.Allocate(cache, needed_size, 8, false);
3433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  } else {
3443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    SpinMutexLock l(&fallback_mutex);
3453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    AllocatorCache *cache = &fallback_allocator_cache;
3463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    allocated = allocator.Allocate(cache, needed_size, 8, false);
3473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
3483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  uptr alloc_beg = reinterpret_cast<uptr>(allocated);
3493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // Clear the first allocated word (an old kMemalignMagic may still be there).
3503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  reinterpret_cast<uptr *>(alloc_beg)[0] = 0;
3513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  uptr alloc_end = alloc_beg + needed_size;
3523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  uptr beg_plus_redzone = alloc_beg + rz_size;
3533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  uptr user_beg = beg_plus_redzone;
3543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (!IsAligned(user_beg, alignment))
3553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    user_beg = RoundUpTo(user_beg, alignment);
3563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  uptr user_end = user_beg + size;
3573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  CHECK_LE(user_end, alloc_end);
3583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  uptr chunk_beg = user_beg - kChunkHeaderSize;
3593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  AsanChunk *m = reinterpret_cast<AsanChunk *>(chunk_beg);
3603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  m->chunk_state = CHUNK_ALLOCATED;
3613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  m->alloc_type = alloc_type;
3623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  m->rz_log = rz_log;
3633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  u32 alloc_tid = t ? t->tid() : 0;
3643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  m->alloc_tid = alloc_tid;
3653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  CHECK_EQ(alloc_tid, m->alloc_tid);  // Does alloc_tid fit into the bitfield?
3663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  m->free_tid = kInvalidTid;
3673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  m->from_memalign = user_beg != beg_plus_redzone;
3683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (m->from_memalign) {
3693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    CHECK_LE(beg_plus_redzone + 2 * sizeof(uptr), user_beg);
3703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    uptr *memalign_magic = reinterpret_cast<uptr *>(alloc_beg);
3713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    memalign_magic[0] = kMemalignMagic;
3723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    memalign_magic[1] = chunk_beg;
3733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
3743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (using_primary_allocator) {
3753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    CHECK(size);
3763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    m->user_requested_size = size;
3773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    CHECK(allocator.FromPrimary(allocated));
3783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  } else {
3793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    CHECK(!allocator.FromPrimary(allocated));
3803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    m->user_requested_size = SizeClassMap::kMaxSize;
3813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    uptr *meta = reinterpret_cast<uptr *>(allocator.GetMetaData(allocated));
3823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    meta[0] = size;
3833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    meta[1] = chunk_beg;
3843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
3853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (flags()->use_stack_depot) {
3873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    m->alloc_context_id = StackDepotPut(stack->trace, stack->size);
3883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  } else {
3893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    m->alloc_context_id = 0;
3903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    StackTrace::CompressStack(stack, m->AllocStackBeg(), m->AllocStackSize());
3913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
3923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  uptr size_rounded_down_to_granularity = RoundDownTo(size, SHADOW_GRANULARITY);
3943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // Unpoison the bulk of the memory region.
3953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (size_rounded_down_to_granularity)
3963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    PoisonShadow(user_beg, size_rounded_down_to_granularity, 0);
3973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // Deal with the end of the region if size is not aligned to granularity.
3983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (size != size_rounded_down_to_granularity && flags()->poison_heap) {
3993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    u8 *shadow = (u8*)MemToShadow(user_beg + size_rounded_down_to_granularity);
4003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    *shadow = size & (SHADOW_GRANULARITY - 1);
4013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
4023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  AsanStats &thread_stats = GetCurrentThreadStats();
4043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  thread_stats.mallocs++;
4053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  thread_stats.malloced += size;
4063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  thread_stats.malloced_redzones += needed_size - size;
4073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  uptr class_id = Min(kNumberOfSizeClasses, SizeClassMap::ClassID(needed_size));
4083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  thread_stats.malloced_by_size[class_id]++;
4093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (needed_size > SizeClassMap::kMaxSize)
4103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    thread_stats.malloc_large++;
4113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  void *res = reinterpret_cast<void *>(user_beg);
4133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  ASAN_MALLOC_HOOK(res, size);
4143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  return res;
4153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4173c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void Deallocate(void *ptr, StackTrace *stack, AllocType alloc_type) {
4183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  uptr p = reinterpret_cast<uptr>(ptr);
4193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (p == 0) return;
4203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  ASAN_FREE_HOOK(ptr);
4213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  uptr chunk_beg = p - kChunkHeaderSize;
4223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  AsanChunk *m = reinterpret_cast<AsanChunk *>(chunk_beg);
4233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  u8 old_chunk_state = CHUNK_ALLOCATED;
4253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // Flip the chunk_state atomically to avoid race on double-free.
4263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (!atomic_compare_exchange_strong((atomic_uint8_t*)m, &old_chunk_state,
4273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry                                      CHUNK_QUARANTINE, memory_order_relaxed)) {
4283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    if (old_chunk_state == CHUNK_QUARANTINE)
4293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      ReportDoubleFree((uptr)ptr, stack);
4303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    else
4313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      ReportFreeNotMalloced((uptr)ptr, stack);
4323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
4333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  CHECK_EQ(CHUNK_ALLOCATED, old_chunk_state);
4343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (m->alloc_type != alloc_type && flags()->alloc_dealloc_mismatch)
4363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    ReportAllocTypeMismatch((uptr)ptr, stack,
4373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry                            (AllocType)m->alloc_type, (AllocType)alloc_type);
4383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  CHECK_GE(m->alloc_tid, 0);
4403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (SANITIZER_WORDSIZE == 64)  // On 32-bits this resides in user area.
4413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    CHECK_EQ(m->free_tid, kInvalidTid);
4423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  AsanThread *t = GetCurrentThread();
4433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  m->free_tid = t ? t->tid() : 0;
4443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (flags()->use_stack_depot) {
4453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    m->free_context_id = StackDepotPut(stack->trace, stack->size);
4463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  } else {
4473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    m->free_context_id = 0;
4483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    StackTrace::CompressStack(stack, m->FreeStackBeg(), m->FreeStackSize());
4493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
4503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  CHECK(m->chunk_state == CHUNK_QUARANTINE);
4513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // Poison the region.
4523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  PoisonShadow(m->Beg(),
4533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry               RoundUpTo(m->UsedSize(), SHADOW_GRANULARITY),
4543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry               kAsanHeapFreeMagic);
4553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  AsanStats &thread_stats = GetCurrentThreadStats();
4573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  thread_stats.frees++;
4583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  thread_stats.freed += m->UsedSize();
4593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // Push into quarantine.
4613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (t) {
4623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    AsanThreadLocalMallocStorage *ms = &t->malloc_storage();
4633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    AllocatorCache *ac = GetAllocatorCache(ms);
4643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    quarantine.Put(GetQuarantineCache(ms), QuarantineCallback(ac),
4653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry                   m, m->UsedSize());
4663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  } else {
4673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    SpinMutexLock l(&fallback_mutex);
4683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    AllocatorCache *ac = &fallback_allocator_cache;
4693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    quarantine.Put(&fallback_quarantine_cache, QuarantineCallback(ac),
4703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry                   m, m->UsedSize());
4713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
4723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4743c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic void *Reallocate(void *old_ptr, uptr new_size, StackTrace *stack) {
4753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  CHECK(old_ptr && new_size);
4763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  uptr p = reinterpret_cast<uptr>(old_ptr);
4773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  uptr chunk_beg = p - kChunkHeaderSize;
4783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  AsanChunk *m = reinterpret_cast<AsanChunk *>(chunk_beg);
4793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  AsanStats &thread_stats = GetCurrentThreadStats();
4813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  thread_stats.reallocs++;
4823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  thread_stats.realloced += new_size;
4833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  CHECK(m->chunk_state == CHUNK_ALLOCATED);
4853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  uptr old_size = m->UsedSize();
4863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  uptr memcpy_size = Min(new_size, old_size);
4873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  void *new_ptr = Allocate(new_size, 8, stack, FROM_MALLOC);
4883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (new_ptr) {
4893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    CHECK_NE(REAL(memcpy), (void*)0);
4903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    REAL(memcpy)(new_ptr, old_ptr, memcpy_size);
4913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    Deallocate(old_ptr, stack, FROM_MALLOC);
4923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
4933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  return new_ptr;
4943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4963c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic AsanChunk *GetAsanChunkByAddr(uptr p) {
4973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  void *ptr = reinterpret_cast<void *>(p);
4983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  uptr alloc_beg = reinterpret_cast<uptr>(allocator.GetBlockBegin(ptr));
4993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (!alloc_beg) return 0;
5003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  uptr *memalign_magic = reinterpret_cast<uptr *>(alloc_beg);
5013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (memalign_magic[0] == kMemalignMagic) {
5023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    AsanChunk *m = reinterpret_cast<AsanChunk *>(memalign_magic[1]);
5033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    CHECK(m->from_memalign);
5043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    return m;
5053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
5063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (!allocator.FromPrimary(ptr)) {
5073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    uptr *meta = reinterpret_cast<uptr *>(
5083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry        allocator.GetMetaData(reinterpret_cast<void *>(alloc_beg)));
5093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    AsanChunk *m = reinterpret_cast<AsanChunk *>(meta[1]);
5103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    return m;
5113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
5123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  uptr actual_size = allocator.GetActuallyAllocatedSize(ptr);
5133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  CHECK_LE(actual_size, SizeClassMap::kMaxSize);
5143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // We know the actually allocted size, but we don't know the redzone size.
5153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // Just try all possible redzone sizes.
5163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  for (u32 rz_log = 0; rz_log < 8; rz_log++) {
5173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    u32 rz_size = RZLog2Size(rz_log);
5183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    uptr max_possible_size = actual_size - rz_size;
5193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    if (ComputeRZLog(max_possible_size) != rz_log)
5203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      continue;
5213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    return reinterpret_cast<AsanChunk *>(
5223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry        alloc_beg + rz_size - kChunkHeaderSize);
5233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
5243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  return 0;
5253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5273c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic uptr AllocationSize(uptr p) {
5283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  AsanChunk *m = GetAsanChunkByAddr(p);
5293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (!m) return 0;
5303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (m->chunk_state != CHUNK_ALLOCATED) return 0;
5313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (m->Beg() != p) return 0;
5323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  return m->UsedSize();
5333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// We have an address between two chunks, and we want to report just one.
5363c827367444ee418f129b2c238299f49d3264554Jarkko PoyryAsanChunk *ChooseChunk(uptr addr,
5373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry                       AsanChunk *left_chunk, AsanChunk *right_chunk) {
5383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // Prefer an allocated chunk over freed chunk and freed chunk
5393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // over available chunk.
5403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (left_chunk->chunk_state != right_chunk->chunk_state) {
5413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    if (left_chunk->chunk_state == CHUNK_ALLOCATED)
5423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      return left_chunk;
5433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    if (right_chunk->chunk_state == CHUNK_ALLOCATED)
5443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      return right_chunk;
5453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    if (left_chunk->chunk_state == CHUNK_QUARANTINE)
5463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      return left_chunk;
5473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    if (right_chunk->chunk_state == CHUNK_QUARANTINE)
5483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      return right_chunk;
5493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
5503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // Same chunk_state: choose based on offset.
5513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  sptr l_offset = 0, r_offset = 0;
5523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  CHECK(AsanChunkView(left_chunk).AddrIsAtRight(addr, 1, &l_offset));
5533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  CHECK(AsanChunkView(right_chunk).AddrIsAtLeft(addr, 1, &r_offset));
5543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (l_offset < r_offset)
5553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    return left_chunk;
5563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  return right_chunk;
5573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5593c827367444ee418f129b2c238299f49d3264554Jarkko PoyryAsanChunkView FindHeapChunkByAddress(uptr addr) {
5603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  AsanChunk *m1 = GetAsanChunkByAddr(addr);
5613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (!m1) return AsanChunkView(m1);
5623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  sptr offset = 0;
5633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (AsanChunkView(m1).AddrIsAtLeft(addr, 1, &offset)) {
5643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    // The address is in the chunk's left redzone, so maybe it is actually
5653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    // a right buffer overflow from the other chunk to the left.
5663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    // Search a bit to the left to see if there is another chunk.
5673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    AsanChunk *m2 = 0;
5683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    for (uptr l = 1; l < GetPageSizeCached(); l++) {
5693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      m2 = GetAsanChunkByAddr(addr - l);
5703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      if (m2 == m1) continue;  // Still the same chunk.
5713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      break;
5723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    }
5733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    if (m2 && AsanChunkView(m2).AddrIsAtRight(addr, 1, &offset))
5743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry      m1 = ChooseChunk(addr, m2, m1);
5753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
5763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  return AsanChunkView(m1);
5773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5793c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid AsanThreadLocalMallocStorage::CommitBack() {
5803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  AllocatorCache *ac = GetAllocatorCache(this);
5813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  quarantine.Drain(GetQuarantineCache(this), QuarantineCallback(ac));
5823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  allocator.SwallowCache(GetAllocatorCache(this));
5833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5853c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid PrintInternalAllocatorStats() {
5863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  allocator.PrintStats();
5873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5893c827367444ee418f129b2c238299f49d3264554Jarkko PoyrySANITIZER_INTERFACE_ATTRIBUTE
5903c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid *asan_memalign(uptr alignment, uptr size, StackTrace *stack,
5913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry                    AllocType alloc_type) {
5923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  return Allocate(size, alignment, stack, alloc_type);
5933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5953c827367444ee418f129b2c238299f49d3264554Jarkko PoyrySANITIZER_INTERFACE_ATTRIBUTE
5963c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid asan_free(void *ptr, StackTrace *stack, AllocType alloc_type) {
5973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  Deallocate(ptr, stack, alloc_type);
5983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6003c827367444ee418f129b2c238299f49d3264554Jarkko PoyrySANITIZER_INTERFACE_ATTRIBUTE
6013c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid *asan_malloc(uptr size, StackTrace *stack) {
6023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  return Allocate(size, 8, stack, FROM_MALLOC);
6033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6053c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid *asan_calloc(uptr nmemb, uptr size, StackTrace *stack) {
6063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (CallocShouldReturnNullDueToOverflow(size, nmemb)) return 0;
6073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  void *ptr = Allocate(nmemb * size, 8, stack, FROM_MALLOC);
6083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // If the memory comes from the secondary allocator no need to clear it
6093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // as it comes directly from mmap.
6103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (ptr && allocator.FromPrimary(ptr))
6113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    REAL(memset)(ptr, 0, nmemb * size);
6123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  return ptr;
6133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6153c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid *asan_realloc(void *p, uptr size, StackTrace *stack) {
6163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (p == 0)
6173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    return Allocate(size, 8, stack, FROM_MALLOC);
6183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (size == 0) {
6193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    Deallocate(p, stack, FROM_MALLOC);
6203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    return 0;
6213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
6223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  return Reallocate(p, size, stack);
6233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6253c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid *asan_valloc(uptr size, StackTrace *stack) {
6263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  return Allocate(size, GetPageSizeCached(), stack, FROM_MALLOC);
6273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6293c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid *asan_pvalloc(uptr size, StackTrace *stack) {
6303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  uptr PageSize = GetPageSizeCached();
6313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  size = RoundUpTo(size, PageSize);
6323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (size == 0) {
6333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    // pvalloc(0) should allocate one page.
6343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    size = PageSize;
6353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
6363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  return Allocate(size, PageSize, stack, FROM_MALLOC);
6373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6393c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint asan_posix_memalign(void **memptr, uptr alignment, uptr size,
6403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry                        StackTrace *stack) {
6413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  void *ptr = Allocate(size, alignment, stack, FROM_MALLOC);
6423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  CHECK(IsAligned((uptr)ptr, alignment));
6433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  *memptr = ptr;
6443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  return 0;
6453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6473c827367444ee418f129b2c238299f49d3264554Jarkko Poyryuptr asan_malloc_usable_size(void *ptr, StackTrace *stack) {
6483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  CHECK(stack);
6493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (ptr == 0) return 0;
6503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  uptr usable_size = AllocationSize(reinterpret_cast<uptr>(ptr));
6513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (flags()->check_malloc_usable_size && (usable_size == 0))
6523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    ReportMallocUsableSizeNotOwned((uptr)ptr, stack);
6533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  return usable_size;
6543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6563c827367444ee418f129b2c238299f49d3264554Jarkko Poyryuptr asan_mz_size(const void *ptr) {
6573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  return AllocationSize(reinterpret_cast<uptr>(ptr));
6583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6603c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid asan_mz_force_lock() {
6613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  allocator.ForceLock();
6623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  fallback_mutex.Lock();
6633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6653c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid asan_mz_force_unlock() {
6663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  fallback_mutex.Unlock();
6673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  allocator.ForceUnlock();
6683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}  // namespace __asan
6713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// ---------------------- Interface ---------------- {{{1
6733c827367444ee418f129b2c238299f49d3264554Jarkko Poyryusing namespace __asan;  // NOLINT
6743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// ASan allocator doesn't reserve extra bytes, so normally we would
6763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// just return "size". We don't want to expose our redzone sizes, etc here.
6773c827367444ee418f129b2c238299f49d3264554Jarkko Poyryuptr __asan_get_estimated_allocated_size(uptr size) {
6783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  return size;
6793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6813c827367444ee418f129b2c238299f49d3264554Jarkko Poyrybool __asan_get_ownership(const void *p) {
6823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  uptr ptr = reinterpret_cast<uptr>(p);
6833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  return (AllocationSize(ptr) > 0);
6843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6863c827367444ee418f129b2c238299f49d3264554Jarkko Poyryuptr __asan_get_allocated_size(const void *p) {
6873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (p == 0) return 0;
6883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  uptr ptr = reinterpret_cast<uptr>(p);
6893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  uptr allocated_size = AllocationSize(ptr);
6903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  // Die if p is not malloced or if it is already freed.
6913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  if (allocated_size == 0) {
6923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    GET_STACK_TRACE_FATAL_HERE;
6933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry    ReportAsanGetAllocatedSizeNotOwned(ptr, &stack);
6943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  }
6953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  return allocated_size;
6963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#if !SANITIZER_SUPPORTS_WEAK_HOOKS
6993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry// Provide default (no-op) implementation of malloc hooks.
7003c827367444ee418f129b2c238299f49d3264554Jarkko Poyryextern "C" {
7013c827367444ee418f129b2c238299f49d3264554Jarkko PoyrySANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
7023c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid __asan_malloc_hook(void *ptr, uptr size) {
7033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  (void)ptr;
7043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  (void)size;
7053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7063c827367444ee418f129b2c238299f49d3264554Jarkko PoyrySANITIZER_WEAK_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE
7073c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid __asan_free_hook(void *ptr) {
7083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry  (void)ptr;
7093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}  // extern "C"
7113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif
7123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif  // ASAN_ALLOCATOR_VERSION
7153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry