186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines//===-- asan_allocator.cc -------------------------------------------------===//
286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines//
386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines//                     The LLVM Compiler Infrastructure
486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines//
586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// This file is distributed under the University of Illinois Open Source
686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// License. See LICENSE.TXT for details.
786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines//
886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines//===----------------------------------------------------------------------===//
986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines//
1086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// This file is a part of AddressSanitizer, an address sanity checker.
1186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines//
1286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// Implementation of ASan's memory allocator, 2-nd version.
1386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// This variant uses the allocator from sanitizer_common, i.e. the one shared
1486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// with ThreadSanitizer and MemorySanitizer.
1586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines//
1686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines//===----------------------------------------------------------------------===//
1786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
18799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#include "asan_allocator.h"
1986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#include "asan_mapping.h"
2086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#include "asan_poisoning.h"
2186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#include "asan_report.h"
2286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#include "asan_stack.h"
2386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#include "asan_thread.h"
2486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#include "sanitizer_common/sanitizer_allocator_interface.h"
2586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#include "sanitizer_common/sanitizer_flags.h"
2686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#include "sanitizer_common/sanitizer_internal_defs.h"
2786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#include "sanitizer_common/sanitizer_list.h"
2886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#include "sanitizer_common/sanitizer_stackdepot.h"
2986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#include "sanitizer_common/sanitizer_quarantine.h"
3086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#include "lsan/lsan_common.h"
3186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
3286277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesnamespace __asan {
3386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
3486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// Valid redzone sizes are 16, 32, 64, ... 2048, so we encode them in 3 bits.
3586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// We use adaptive redzones: for larger allocation larger redzones are used.
3686277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesstatic u32 RZLog2Size(u32 rz_log) {
3786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  CHECK_LT(rz_log, 8);
3886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  return 16 << rz_log;
3986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
4086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
4186277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesstatic u32 RZSize2Log(u32 rz_size) {
4286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  CHECK_GE(rz_size, 16);
4386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  CHECK_LE(rz_size, 2048);
4486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  CHECK(IsPowerOfTwo(rz_size));
4586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  u32 res = Log2(rz_size) - 4;
4686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  CHECK_EQ(rz_size, RZLog2Size(res));
4786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  return res;
4886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
4986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
5086277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesstatic AsanAllocator &get_allocator();
5186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
5286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// The memory chunk allocated from the underlying allocator looks like this:
5386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// L L L L L L H H U U U U U U R R
5486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines//   L -- left redzone words (0 or more bytes)
5586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines//   H -- ChunkHeader (16 bytes), which is also a part of the left redzone.
5686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines//   U -- user memory.
5786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines//   R -- right redzone (0 or more bytes)
5886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// ChunkBase consists of ChunkHeader and other bytes that overlap with user
5986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// memory.
6086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
6186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// If the left redzone is greater than the ChunkHeader size we store a magic
6286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// value in the first uptr word of the memory block and store the address of
6386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// ChunkBase in the next uptr.
6486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// M B L L L L L L L L L  H H U U U U U U
6586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines//   |                    ^
6686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines//   ---------------------|
6786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines//   M -- magic value kAllocBegMagic
6886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines//   B -- address of ChunkHeader pointing to the first 'H'
6986277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesstatic const uptr kAllocBegMagic = 0xCC6E96B9;
7086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
7186277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesstruct ChunkHeader {
7286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // 1-st 8 bytes.
7386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  u32 chunk_state       : 8;  // Must be first.
7486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  u32 alloc_tid         : 24;
7586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
7686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  u32 free_tid          : 24;
7786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  u32 from_memalign     : 1;
7886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  u32 alloc_type        : 2;
7986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  u32 rz_log            : 3;
8086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  u32 lsan_tag          : 2;
8186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // 2-nd 8 bytes
8286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // This field is used for small sizes. For large sizes it is equal to
8386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // SizeClassMap::kMaxSize and the actual size is stored in the
8486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // SecondaryAllocator's metadata.
8586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  u32 user_requested_size;
8686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  u32 alloc_context_id;
8786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines};
8886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
8986277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesstruct ChunkBase : ChunkHeader {
9086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // Header2, intersects with user memory.
9186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  u32 free_context_id;
9286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines};
9386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
9486277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesstatic const uptr kChunkHeaderSize = sizeof(ChunkHeader);
9586277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesstatic const uptr kChunkHeader2Size = sizeof(ChunkBase) - kChunkHeaderSize;
9686277eb844c4983c81de62d7c050e92fe7155788Stephen HinesCOMPILER_CHECK(kChunkHeaderSize == 16);
9786277eb844c4983c81de62d7c050e92fe7155788Stephen HinesCOMPILER_CHECK(kChunkHeader2Size <= 16);
9886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
9986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// Every chunk of memory allocated by this allocator can be in one of 3 states:
10086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// CHUNK_AVAILABLE: the chunk is in the free list and ready to be allocated.
10186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// CHUNK_ALLOCATED: the chunk is allocated and not yet freed.
10286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// CHUNK_QUARANTINE: the chunk was freed and put into quarantine zone.
10386277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesenum {
10486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  CHUNK_AVAILABLE  = 0,  // 0 is the default value even if we didn't set it.
10586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  CHUNK_ALLOCATED  = 2,
10686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  CHUNK_QUARANTINE = 3
10786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines};
10886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
10986277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesstruct AsanChunk: ChunkBase {
11086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  uptr Beg() { return reinterpret_cast<uptr>(this) + kChunkHeaderSize; }
11186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  uptr UsedSize(bool locked_version = false) {
11286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    if (user_requested_size != SizeClassMap::kMaxSize)
11386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      return user_requested_size;
11486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    return *reinterpret_cast<uptr *>(
11586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines               get_allocator().GetMetaData(AllocBeg(locked_version)));
11686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  }
11786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void *AllocBeg(bool locked_version = false) {
11886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    if (from_memalign) {
11986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      if (locked_version)
12086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines        return get_allocator().GetBlockBeginFastLocked(
12186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines            reinterpret_cast<void *>(this));
12286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      return get_allocator().GetBlockBegin(reinterpret_cast<void *>(this));
12386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    }
12486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    return reinterpret_cast<void*>(Beg() - RZLog2Size(rz_log));
12586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  }
12686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  bool AddrIsInside(uptr addr, bool locked_version = false) {
12786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    return (addr >= Beg()) && (addr < Beg() + UsedSize(locked_version));
12886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  }
12986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines};
13086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
13186277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesstruct QuarantineCallback {
13286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  explicit QuarantineCallback(AllocatorCache *cache)
13386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      : cache_(cache) {
13486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  }
13586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
13686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void Recycle(AsanChunk *m) {
13786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    CHECK_EQ(m->chunk_state, CHUNK_QUARANTINE);
13886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    atomic_store((atomic_uint8_t*)m, CHUNK_AVAILABLE, memory_order_relaxed);
13986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    CHECK_NE(m->alloc_tid, kInvalidTid);
14086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    CHECK_NE(m->free_tid, kInvalidTid);
14186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    PoisonShadow(m->Beg(),
14286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines                 RoundUpTo(m->UsedSize(), SHADOW_GRANULARITY),
14386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines                 kAsanHeapLeftRedzoneMagic);
14486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    void *p = reinterpret_cast<void *>(m->AllocBeg());
14586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    if (p != m) {
14686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      uptr *alloc_magic = reinterpret_cast<uptr *>(p);
14786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      CHECK_EQ(alloc_magic[0], kAllocBegMagic);
14886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      // Clear the magic value, as allocator internals may overwrite the
14986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      // contents of deallocated chunk, confusing GetAsanChunk lookup.
15086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      alloc_magic[0] = 0;
15186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      CHECK_EQ(alloc_magic[1], reinterpret_cast<uptr>(m));
15286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    }
15386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
15486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    // Statistics.
15586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    AsanStats &thread_stats = GetCurrentThreadStats();
15686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    thread_stats.real_frees++;
15786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    thread_stats.really_freed += m->UsedSize();
15886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
15986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    get_allocator().Deallocate(cache_, p);
16086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  }
16186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
16286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void *Allocate(uptr size) {
16386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    return get_allocator().Allocate(cache_, size, 1, false);
16486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  }
16586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
16686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void Deallocate(void *p) {
16786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    get_allocator().Deallocate(cache_, p);
16886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  }
16986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
17086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  AllocatorCache *cache_;
17186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines};
17286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
17386277eb844c4983c81de62d7c050e92fe7155788Stephen Hinestypedef Quarantine<QuarantineCallback, AsanChunk> AsanQuarantine;
17486277eb844c4983c81de62d7c050e92fe7155788Stephen Hinestypedef AsanQuarantine::Cache QuarantineCache;
17586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
17686277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid AsanMapUnmapCallback::OnMap(uptr p, uptr size) const {
17786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  PoisonShadow(p, size, kAsanHeapLeftRedzoneMagic);
17886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // Statistics.
17986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  AsanStats &thread_stats = GetCurrentThreadStats();
18086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  thread_stats.mmaps++;
18186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  thread_stats.mmaped += size;
18286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
18386277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid AsanMapUnmapCallback::OnUnmap(uptr p, uptr size) const {
18486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  PoisonShadow(p, size, 0);
18586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // We are about to unmap a chunk of user memory.
18686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // Mark the corresponding shadow memory as not needed.
18786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  FlushUnneededASanShadowMemory(p, size);
18886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // Statistics.
18986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  AsanStats &thread_stats = GetCurrentThreadStats();
19086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  thread_stats.munmaps++;
19186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  thread_stats.munmaped += size;
19286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
19386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
19486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// We can not use THREADLOCAL because it is not supported on some of the
19586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// platforms we care about (OSX 10.6, Android).
19686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// static THREADLOCAL AllocatorCache cache;
19786277eb844c4983c81de62d7c050e92fe7155788Stephen HinesAllocatorCache *GetAllocatorCache(AsanThreadLocalMallocStorage *ms) {
19886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  CHECK(ms);
19986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  return &ms->allocator_cache;
20086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
20186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
20286277eb844c4983c81de62d7c050e92fe7155788Stephen HinesQuarantineCache *GetQuarantineCache(AsanThreadLocalMallocStorage *ms) {
20386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  CHECK(ms);
20486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  CHECK_LE(sizeof(QuarantineCache), sizeof(ms->quarantine_cache));
20586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  return reinterpret_cast<QuarantineCache *>(ms->quarantine_cache);
20686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
20786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
20886277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid AllocatorOptions::SetFrom(const Flags *f, const CommonFlags *cf) {
20986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  quarantine_size_mb = f->quarantine_size_mb;
21086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  min_redzone = f->redzone;
21186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  max_redzone = f->max_redzone;
21286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  may_return_null = cf->allocator_may_return_null;
21386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  alloc_dealloc_mismatch = f->alloc_dealloc_mismatch;
21486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
21586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
21686277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid AllocatorOptions::CopyTo(Flags *f, CommonFlags *cf) {
21786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  f->quarantine_size_mb = quarantine_size_mb;
21886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  f->redzone = min_redzone;
21986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  f->max_redzone = max_redzone;
22086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  cf->allocator_may_return_null = may_return_null;
22186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  f->alloc_dealloc_mismatch = alloc_dealloc_mismatch;
22286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
22386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
22486277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesstruct Allocator {
22586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  static const uptr kMaxAllowedMallocSize =
226c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar      FIRST_32_SECOND_64(3UL << 30, 1ULL << 40);
22786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  static const uptr kMaxThreadLocalQuarantine =
22886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      FIRST_32_SECOND_64(1 << 18, 1 << 20);
22986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
23086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  AsanAllocator allocator;
23186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  AsanQuarantine quarantine;
23286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  StaticSpinMutex fallback_mutex;
23386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  AllocatorCache fallback_allocator_cache;
23486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  QuarantineCache fallback_quarantine_cache;
23586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
23686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // ------------------- Options --------------------------
23786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  atomic_uint16_t min_redzone;
23886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  atomic_uint16_t max_redzone;
23986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  atomic_uint8_t alloc_dealloc_mismatch;
24086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
24186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // ------------------- Initialization ------------------------
24286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  explicit Allocator(LinkerInitialized)
24386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      : quarantine(LINKER_INITIALIZED),
24486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines        fallback_quarantine_cache(LINKER_INITIALIZED) {}
24586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
24686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void CheckOptions(const AllocatorOptions &options) const {
24786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    CHECK_GE(options.min_redzone, 16);
24886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    CHECK_GE(options.max_redzone, options.min_redzone);
24986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    CHECK_LE(options.max_redzone, 2048);
25086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    CHECK(IsPowerOfTwo(options.min_redzone));
25186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    CHECK(IsPowerOfTwo(options.max_redzone));
25286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  }
25386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
25486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void SharedInitCode(const AllocatorOptions &options) {
25586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    CheckOptions(options);
25686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    quarantine.Init((uptr)options.quarantine_size_mb << 20,
25786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines                    kMaxThreadLocalQuarantine);
25886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    atomic_store(&alloc_dealloc_mismatch, options.alloc_dealloc_mismatch,
25986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines                 memory_order_release);
26086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    atomic_store(&min_redzone, options.min_redzone, memory_order_release);
26186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    atomic_store(&max_redzone, options.max_redzone, memory_order_release);
26286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  }
26386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
26486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void Initialize(const AllocatorOptions &options) {
26586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    allocator.Init(options.may_return_null);
26686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    SharedInitCode(options);
26786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  }
26886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
26986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void ReInitialize(const AllocatorOptions &options) {
27086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    allocator.SetMayReturnNull(options.may_return_null);
27186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    SharedInitCode(options);
27286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  }
27386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
27486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void GetOptions(AllocatorOptions *options) const {
27586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    options->quarantine_size_mb = quarantine.GetSize() >> 20;
27686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    options->min_redzone = atomic_load(&min_redzone, memory_order_acquire);
27786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    options->max_redzone = atomic_load(&max_redzone, memory_order_acquire);
27886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    options->may_return_null = allocator.MayReturnNull();
27986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    options->alloc_dealloc_mismatch =
28086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines        atomic_load(&alloc_dealloc_mismatch, memory_order_acquire);
28186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  }
28286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
28386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // -------------------- Helper methods. -------------------------
28486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  uptr ComputeRZLog(uptr user_requested_size) {
28586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    u32 rz_log =
28686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      user_requested_size <= 64        - 16   ? 0 :
28786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      user_requested_size <= 128       - 32   ? 1 :
28886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      user_requested_size <= 512       - 64   ? 2 :
28986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      user_requested_size <= 4096      - 128  ? 3 :
29086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      user_requested_size <= (1 << 14) - 256  ? 4 :
29186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      user_requested_size <= (1 << 15) - 512  ? 5 :
29286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      user_requested_size <= (1 << 16) - 1024 ? 6 : 7;
29386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    u32 min_rz = atomic_load(&min_redzone, memory_order_acquire);
29486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    u32 max_rz = atomic_load(&max_redzone, memory_order_acquire);
29586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    return Min(Max(rz_log, RZSize2Log(min_rz)), RZSize2Log(max_rz));
29686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  }
29786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
29886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // We have an address between two chunks, and we want to report just one.
29986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  AsanChunk *ChooseChunk(uptr addr, AsanChunk *left_chunk,
30086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines                         AsanChunk *right_chunk) {
30186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    // Prefer an allocated chunk over freed chunk and freed chunk
30286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    // over available chunk.
30386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    if (left_chunk->chunk_state != right_chunk->chunk_state) {
30486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      if (left_chunk->chunk_state == CHUNK_ALLOCATED)
30586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines        return left_chunk;
30686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      if (right_chunk->chunk_state == CHUNK_ALLOCATED)
30786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines        return right_chunk;
30886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      if (left_chunk->chunk_state == CHUNK_QUARANTINE)
30986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines        return left_chunk;
31086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      if (right_chunk->chunk_state == CHUNK_QUARANTINE)
31186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines        return right_chunk;
31286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    }
31386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    // Same chunk_state: choose based on offset.
31486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    sptr l_offset = 0, r_offset = 0;
31586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    CHECK(AsanChunkView(left_chunk).AddrIsAtRight(addr, 1, &l_offset));
31686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    CHECK(AsanChunkView(right_chunk).AddrIsAtLeft(addr, 1, &r_offset));
31786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    if (l_offset < r_offset)
31886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      return left_chunk;
31986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    return right_chunk;
32086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  }
32186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
32286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // -------------------- Allocation/Deallocation routines ---------------
32386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void *Allocate(uptr size, uptr alignment, BufferedStackTrace *stack,
32486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines                 AllocType alloc_type, bool can_fill) {
32586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    if (UNLIKELY(!asan_inited))
32686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      AsanInitFromRtl();
32786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    Flags &fl = *flags();
32886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    CHECK(stack);
32986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    const uptr min_alignment = SHADOW_GRANULARITY;
33086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    if (alignment < min_alignment)
33186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      alignment = min_alignment;
33286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    if (size == 0) {
33386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      // We'd be happy to avoid allocating memory for zero-size requests, but
33486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      // some programs/tests depend on this behavior and assume that malloc
33586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      // would not return NULL even for zero-size allocations. Moreover, it
33686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      // looks like operator new should never return NULL, and results of
33786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      // consecutive "new" calls must be different even if the allocated size
33886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      // is zero.
33986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      size = 1;
34086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    }
34186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    CHECK(IsPowerOfTwo(alignment));
34286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    uptr rz_log = ComputeRZLog(size);
34386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    uptr rz_size = RZLog2Size(rz_log);
34486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    uptr rounded_size = RoundUpTo(Max(size, kChunkHeader2Size), alignment);
34586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    uptr needed_size = rounded_size + rz_size;
34686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    if (alignment > min_alignment)
34786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      needed_size += alignment;
34886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    bool using_primary_allocator = true;
34986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    // If we are allocating from the secondary allocator, there will be no
35086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    // automatic right redzone, so add the right redzone manually.
35186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    if (!PrimaryAllocator::CanAllocate(needed_size, alignment)) {
35286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      needed_size += rz_size;
35386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      using_primary_allocator = false;
35486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    }
35586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    CHECK(IsAligned(needed_size, min_alignment));
35686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    if (size > kMaxAllowedMallocSize || needed_size > kMaxAllowedMallocSize) {
357cdce50bda3603770cc4ef80cbb613c78b8e47a17Pirama Arumuga Nainar      Report("WARNING: AddressSanitizer failed to allocate 0x%zx bytes\n",
35886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines             (void*)size);
35986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      return allocator.ReturnNullOrDie();
36086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    }
36186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
36286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    AsanThread *t = GetCurrentThread();
36386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    void *allocated;
36486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    bool check_rss_limit = true;
36586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    if (t) {
36686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      AllocatorCache *cache = GetAllocatorCache(&t->malloc_storage());
36786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      allocated =
36886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines          allocator.Allocate(cache, needed_size, 8, false, check_rss_limit);
36986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    } else {
37086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      SpinMutexLock l(&fallback_mutex);
37186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      AllocatorCache *cache = &fallback_allocator_cache;
37286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      allocated =
37386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines          allocator.Allocate(cache, needed_size, 8, false, check_rss_limit);
37486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    }
37586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
37686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    if (!allocated)
37786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      return allocator.ReturnNullOrDie();
37886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
37986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    if (*(u8 *)MEM_TO_SHADOW((uptr)allocated) == 0 && CanPoisonMemory()) {
38086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      // Heap poisoning is enabled, but the allocator provides an unpoisoned
38186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      // chunk. This is possible if CanPoisonMemory() was false for some
38286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      // time, for example, due to flags()->start_disabled.
38386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      // Anyway, poison the block before using it for anything else.
38486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      uptr allocated_size = allocator.GetActuallyAllocatedSize(allocated);
38586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      PoisonShadow((uptr)allocated, allocated_size, kAsanHeapLeftRedzoneMagic);
38686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    }
38786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
38886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    uptr alloc_beg = reinterpret_cast<uptr>(allocated);
38986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    uptr alloc_end = alloc_beg + needed_size;
39086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    uptr beg_plus_redzone = alloc_beg + rz_size;
39186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    uptr user_beg = beg_plus_redzone;
39286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    if (!IsAligned(user_beg, alignment))
39386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      user_beg = RoundUpTo(user_beg, alignment);
39486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    uptr user_end = user_beg + size;
39586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    CHECK_LE(user_end, alloc_end);
39686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    uptr chunk_beg = user_beg - kChunkHeaderSize;
39786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    AsanChunk *m = reinterpret_cast<AsanChunk *>(chunk_beg);
39886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    m->alloc_type = alloc_type;
39986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    m->rz_log = rz_log;
40086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    u32 alloc_tid = t ? t->tid() : 0;
40186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    m->alloc_tid = alloc_tid;
40286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    CHECK_EQ(alloc_tid, m->alloc_tid);  // Does alloc_tid fit into the bitfield?
40386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    m->free_tid = kInvalidTid;
40486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    m->from_memalign = user_beg != beg_plus_redzone;
40586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    if (alloc_beg != chunk_beg) {
40686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      CHECK_LE(alloc_beg+ 2 * sizeof(uptr), chunk_beg);
40786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      reinterpret_cast<uptr *>(alloc_beg)[0] = kAllocBegMagic;
40886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      reinterpret_cast<uptr *>(alloc_beg)[1] = chunk_beg;
40986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    }
41086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    if (using_primary_allocator) {
41186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      CHECK(size);
41286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      m->user_requested_size = size;
41386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      CHECK(allocator.FromPrimary(allocated));
41486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    } else {
41586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      CHECK(!allocator.FromPrimary(allocated));
41686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      m->user_requested_size = SizeClassMap::kMaxSize;
41786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      uptr *meta = reinterpret_cast<uptr *>(allocator.GetMetaData(allocated));
41886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      meta[0] = size;
41986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      meta[1] = chunk_beg;
42086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    }
42186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
42286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    m->alloc_context_id = StackDepotPut(*stack);
42386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
42486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    uptr size_rounded_down_to_granularity =
42586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines        RoundDownTo(size, SHADOW_GRANULARITY);
42686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    // Unpoison the bulk of the memory region.
42786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    if (size_rounded_down_to_granularity)
42886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      PoisonShadow(user_beg, size_rounded_down_to_granularity, 0);
42986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    // Deal with the end of the region if size is not aligned to granularity.
43086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    if (size != size_rounded_down_to_granularity && CanPoisonMemory()) {
43186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      u8 *shadow =
43286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines          (u8 *)MemToShadow(user_beg + size_rounded_down_to_granularity);
43386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      *shadow = fl.poison_partial ? (size & (SHADOW_GRANULARITY - 1)) : 0;
43486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    }
43586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
43686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    AsanStats &thread_stats = GetCurrentThreadStats();
43786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    thread_stats.mallocs++;
43886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    thread_stats.malloced += size;
43986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    thread_stats.malloced_redzones += needed_size - size;
44086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    if (needed_size > SizeClassMap::kMaxSize)
44186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      thread_stats.malloc_large++;
442799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    else
443799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar      thread_stats.malloced_by_size[SizeClassMap::ClassID(needed_size)]++;
44486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
44586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    void *res = reinterpret_cast<void *>(user_beg);
44686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    if (can_fill && fl.max_malloc_fill_size) {
44786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      uptr fill_size = Min(size, (uptr)fl.max_malloc_fill_size);
44886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      REAL(memset)(res, fl.malloc_fill_byte, fill_size);
44986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    }
45086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#if CAN_SANITIZE_LEAKS
45186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    m->lsan_tag = __lsan::DisabledInThisThread() ? __lsan::kIgnored
45286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines                                                 : __lsan::kDirectlyLeaked;
45386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#endif
45486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    // Must be the last mutation of metadata in this function.
45586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    atomic_store((atomic_uint8_t *)m, CHUNK_ALLOCATED, memory_order_release);
45686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    ASAN_MALLOC_HOOK(res, size);
45786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    return res;
45886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  }
45986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
460c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  // Set quarantine flag if chunk is allocated, issue ASan error report on
461c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  // available and quarantined chunks. Return true on success, false otherwise.
462c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  bool AtomicallySetQuarantineFlagIfAllocated(AsanChunk *m, void *ptr,
46386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines                                   BufferedStackTrace *stack) {
46486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    u8 old_chunk_state = CHUNK_ALLOCATED;
46586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    // Flip the chunk_state atomically to avoid race on double-free.
466c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    if (!atomic_compare_exchange_strong((atomic_uint8_t *)m, &old_chunk_state,
467c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar                                        CHUNK_QUARANTINE,
468c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar                                        memory_order_acquire)) {
46986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      ReportInvalidFree(ptr, old_chunk_state, stack);
470c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar      // It's not safe to push a chunk in quarantine on invalid free.
471c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar      return false;
472c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    }
47386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    CHECK_EQ(CHUNK_ALLOCATED, old_chunk_state);
474c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    return true;
47586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  }
47686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
47786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // Expects the chunk to already be marked as quarantined by using
478c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  // AtomicallySetQuarantineFlagIfAllocated.
47986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void QuarantineChunk(AsanChunk *m, void *ptr, BufferedStackTrace *stack,
48086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines                       AllocType alloc_type) {
48186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    CHECK_EQ(m->chunk_state, CHUNK_QUARANTINE);
48286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    CHECK_GE(m->alloc_tid, 0);
48386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    if (SANITIZER_WORDSIZE == 64)  // On 32-bits this resides in user area.
48486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      CHECK_EQ(m->free_tid, kInvalidTid);
48586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    AsanThread *t = GetCurrentThread();
48686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    m->free_tid = t ? t->tid() : 0;
48786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    m->free_context_id = StackDepotPut(*stack);
48886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    // Poison the region.
48986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    PoisonShadow(m->Beg(),
49086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines                 RoundUpTo(m->UsedSize(), SHADOW_GRANULARITY),
49186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines                 kAsanHeapFreeMagic);
49286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
49386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    AsanStats &thread_stats = GetCurrentThreadStats();
49486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    thread_stats.frees++;
49586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    thread_stats.freed += m->UsedSize();
49686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
49786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    // Push into quarantine.
49886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    if (t) {
49986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      AsanThreadLocalMallocStorage *ms = &t->malloc_storage();
50086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      AllocatorCache *ac = GetAllocatorCache(ms);
50186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      quarantine.Put(GetQuarantineCache(ms), QuarantineCallback(ac), m,
50286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines                           m->UsedSize());
50386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    } else {
50486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      SpinMutexLock l(&fallback_mutex);
50586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      AllocatorCache *ac = &fallback_allocator_cache;
50686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      quarantine.Put(&fallback_quarantine_cache, QuarantineCallback(ac), m,
50786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines                           m->UsedSize());
50886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    }
50986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  }
51086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
51186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void Deallocate(void *ptr, uptr delete_size, BufferedStackTrace *stack,
51286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines                  AllocType alloc_type) {
51386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    uptr p = reinterpret_cast<uptr>(ptr);
51486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    if (p == 0) return;
51586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
51686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    uptr chunk_beg = p - kChunkHeaderSize;
51786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    AsanChunk *m = reinterpret_cast<AsanChunk *>(chunk_beg);
518c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
519c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    ASAN_FREE_HOOK(ptr);
520c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    // Must mark the chunk as quarantined before any changes to its metadata.
521c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    // Do not quarantine given chunk if we failed to set CHUNK_QUARANTINE flag.
522c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    if (!AtomicallySetQuarantineFlagIfAllocated(m, ptr, stack)) return;
523c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
524c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    if (m->alloc_type != alloc_type) {
525c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar      if (atomic_load(&alloc_dealloc_mismatch, memory_order_acquire)) {
526c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar        ReportAllocTypeMismatch((uptr)ptr, stack, (AllocType)m->alloc_type,
527c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar                                (AllocType)alloc_type);
528c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar      }
529c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar    }
530c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
53186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    if (delete_size && flags()->new_delete_type_mismatch &&
53286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines        delete_size != m->UsedSize()) {
533c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar      ReportNewDeleteSizeMismatch(p, m->UsedSize(), delete_size, stack);
53486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    }
535c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
53686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    QuarantineChunk(m, ptr, stack, alloc_type);
53786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  }
53886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
53986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void *Reallocate(void *old_ptr, uptr new_size, BufferedStackTrace *stack) {
54086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    CHECK(old_ptr && new_size);
54186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    uptr p = reinterpret_cast<uptr>(old_ptr);
54286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    uptr chunk_beg = p - kChunkHeaderSize;
54386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    AsanChunk *m = reinterpret_cast<AsanChunk *>(chunk_beg);
54486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
54586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    AsanStats &thread_stats = GetCurrentThreadStats();
54686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    thread_stats.reallocs++;
54786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    thread_stats.realloced += new_size;
54886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
54986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    void *new_ptr = Allocate(new_size, 8, stack, FROM_MALLOC, true);
55086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    if (new_ptr) {
55186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      u8 chunk_state = m->chunk_state;
55286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      if (chunk_state != CHUNK_ALLOCATED)
55386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines        ReportInvalidFree(old_ptr, chunk_state, stack);
554799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar      CHECK_NE(REAL(memcpy), nullptr);
55586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      uptr memcpy_size = Min(new_size, m->UsedSize());
55686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      // If realloc() races with free(), we may start copying freed memory.
55786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      // However, we will report racy double-free later anyway.
55886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      REAL(memcpy)(new_ptr, old_ptr, memcpy_size);
55986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      Deallocate(old_ptr, 0, stack, FROM_MALLOC);
56086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    }
56186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    return new_ptr;
56286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  }
56386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
56486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void *Calloc(uptr nmemb, uptr size, BufferedStackTrace *stack) {
56586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    if (CallocShouldReturnNullDueToOverflow(size, nmemb))
56686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      return allocator.ReturnNullOrDie();
56786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    void *ptr = Allocate(nmemb * size, 8, stack, FROM_MALLOC, false);
56886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    // If the memory comes from the secondary allocator no need to clear it
56986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    // as it comes directly from mmap.
57086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    if (ptr && allocator.FromPrimary(ptr))
57186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      REAL(memset)(ptr, 0, nmemb * size);
57286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    return ptr;
57386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  }
57486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
57586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void ReportInvalidFree(void *ptr, u8 chunk_state, BufferedStackTrace *stack) {
57686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    if (chunk_state == CHUNK_QUARANTINE)
57786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      ReportDoubleFree((uptr)ptr, stack);
57886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    else
57986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      ReportFreeNotMalloced((uptr)ptr, stack);
58086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  }
58186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
58286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void CommitBack(AsanThreadLocalMallocStorage *ms) {
58386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    AllocatorCache *ac = GetAllocatorCache(ms);
58486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    quarantine.Drain(GetQuarantineCache(ms), QuarantineCallback(ac));
58586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    allocator.SwallowCache(ac);
58686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  }
58786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
58886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // -------------------------- Chunk lookup ----------------------
58986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
59086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // Assumes alloc_beg == allocator.GetBlockBegin(alloc_beg).
59186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  AsanChunk *GetAsanChunk(void *alloc_beg) {
592799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    if (!alloc_beg) return nullptr;
59386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    if (!allocator.FromPrimary(alloc_beg)) {
59486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      uptr *meta = reinterpret_cast<uptr *>(allocator.GetMetaData(alloc_beg));
59586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      AsanChunk *m = reinterpret_cast<AsanChunk *>(meta[1]);
59686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      return m;
59786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    }
59886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    uptr *alloc_magic = reinterpret_cast<uptr *>(alloc_beg);
59986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    if (alloc_magic[0] == kAllocBegMagic)
60086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      return reinterpret_cast<AsanChunk *>(alloc_magic[1]);
60186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    return reinterpret_cast<AsanChunk *>(alloc_beg);
60286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  }
60386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
60486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  AsanChunk *GetAsanChunkByAddr(uptr p) {
60586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    void *alloc_beg = allocator.GetBlockBegin(reinterpret_cast<void *>(p));
60686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    return GetAsanChunk(alloc_beg);
60786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  }
60886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
60986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // Allocator must be locked when this function is called.
61086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  AsanChunk *GetAsanChunkByAddrFastLocked(uptr p) {
61186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    void *alloc_beg =
61286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines        allocator.GetBlockBeginFastLocked(reinterpret_cast<void *>(p));
61386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    return GetAsanChunk(alloc_beg);
61486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  }
61586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
61686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  uptr AllocationSize(uptr p) {
61786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    AsanChunk *m = GetAsanChunkByAddr(p);
61886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    if (!m) return 0;
61986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    if (m->chunk_state != CHUNK_ALLOCATED) return 0;
62086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    if (m->Beg() != p) return 0;
62186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    return m->UsedSize();
62286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  }
62386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
62486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  AsanChunkView FindHeapChunkByAddress(uptr addr) {
62586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    AsanChunk *m1 = GetAsanChunkByAddr(addr);
62686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    if (!m1) return AsanChunkView(m1);
62786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    sptr offset = 0;
62886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    if (AsanChunkView(m1).AddrIsAtLeft(addr, 1, &offset)) {
62986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      // The address is in the chunk's left redzone, so maybe it is actually
63086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      // a right buffer overflow from the other chunk to the left.
63186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      // Search a bit to the left to see if there is another chunk.
632799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar      AsanChunk *m2 = nullptr;
63386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      for (uptr l = 1; l < GetPageSizeCached(); l++) {
63486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines        m2 = GetAsanChunkByAddr(addr - l);
63586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines        if (m2 == m1) continue;  // Still the same chunk.
63686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines        break;
63786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      }
63886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      if (m2 && AsanChunkView(m2).AddrIsAtRight(addr, 1, &offset))
63986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines        m1 = ChooseChunk(addr, m2, m1);
64086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    }
64186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    return AsanChunkView(m1);
64286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  }
64386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
64486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void PrintStats() {
64586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    allocator.PrintStats();
64686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  }
64786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
64886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void ForceLock() {
64986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    allocator.ForceLock();
65086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    fallback_mutex.Lock();
65186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  }
65286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
65386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void ForceUnlock() {
65486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    fallback_mutex.Unlock();
65586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    allocator.ForceUnlock();
65686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  }
65786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines};
65886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
65986277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesstatic Allocator instance(LINKER_INITIALIZED);
66086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
66186277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesstatic AsanAllocator &get_allocator() {
66286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  return instance.allocator;
66386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
66486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
66586277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesbool AsanChunkView::IsValid() {
666799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  return chunk_ && chunk_->chunk_state != CHUNK_AVAILABLE;
66786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
668c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainarbool AsanChunkView::IsAllocated() {
669c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  return chunk_ && chunk_->chunk_state == CHUNK_ALLOCATED;
670c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar}
67186277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesuptr AsanChunkView::Beg() { return chunk_->Beg(); }
67286277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesuptr AsanChunkView::End() { return Beg() + UsedSize(); }
67386277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesuptr AsanChunkView::UsedSize() { return chunk_->UsedSize(); }
67486277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesuptr AsanChunkView::AllocTid() { return chunk_->alloc_tid; }
67586277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesuptr AsanChunkView::FreeTid() { return chunk_->free_tid; }
67686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
67786277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesstatic StackTrace GetStackTraceFromId(u32 id) {
67886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  CHECK(id);
67986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  StackTrace res = StackDepotGet(id);
68086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  CHECK(res.trace);
68186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  return res;
68286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
68386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
684c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainaru32 AsanChunkView::GetAllocStackId() { return chunk_->alloc_context_id; }
685c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainaru32 AsanChunkView::GetFreeStackId() { return chunk_->free_context_id; }
686c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar
68786277eb844c4983c81de62d7c050e92fe7155788Stephen HinesStackTrace AsanChunkView::GetAllocStack() {
688c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  return GetStackTraceFromId(GetAllocStackId());
68986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
69086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
69186277eb844c4983c81de62d7c050e92fe7155788Stephen HinesStackTrace AsanChunkView::GetFreeStack() {
692c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar  return GetStackTraceFromId(GetFreeStackId());
69386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
69486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
69586277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid InitializeAllocator(const AllocatorOptions &options) {
69686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  instance.Initialize(options);
69786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
69886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
69986277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid ReInitializeAllocator(const AllocatorOptions &options) {
70086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  instance.ReInitialize(options);
70186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
70286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
70386277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid GetAllocatorOptions(AllocatorOptions *options) {
70486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  instance.GetOptions(options);
70586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
70686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
70786277eb844c4983c81de62d7c050e92fe7155788Stephen HinesAsanChunkView FindHeapChunkByAddress(uptr addr) {
70886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  return instance.FindHeapChunkByAddress(addr);
70986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
71086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
71186277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid AsanThreadLocalMallocStorage::CommitBack() {
71286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  instance.CommitBack(this);
71386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
71486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
71586277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid PrintInternalAllocatorStats() {
71686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  instance.PrintStats();
71786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
71886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
71986277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid *asan_memalign(uptr alignment, uptr size, BufferedStackTrace *stack,
72086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines                    AllocType alloc_type) {
72186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  return instance.Allocate(size, alignment, stack, alloc_type, true);
72286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
72386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
72486277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid asan_free(void *ptr, BufferedStackTrace *stack, AllocType alloc_type) {
72586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  instance.Deallocate(ptr, 0, stack, alloc_type);
72686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
72786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
72886277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid asan_sized_free(void *ptr, uptr size, BufferedStackTrace *stack,
72986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines                     AllocType alloc_type) {
73086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  instance.Deallocate(ptr, size, stack, alloc_type);
73186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
73286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
73386277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid *asan_malloc(uptr size, BufferedStackTrace *stack) {
73486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  return instance.Allocate(size, 8, stack, FROM_MALLOC, true);
73586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
73686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
73786277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid *asan_calloc(uptr nmemb, uptr size, BufferedStackTrace *stack) {
73886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  return instance.Calloc(nmemb, size, stack);
73986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
74086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
74186277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid *asan_realloc(void *p, uptr size, BufferedStackTrace *stack) {
742799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  if (!p)
74386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    return instance.Allocate(size, 8, stack, FROM_MALLOC, true);
74486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  if (size == 0) {
74586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    instance.Deallocate(p, 0, stack, FROM_MALLOC);
746799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar    return nullptr;
74786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  }
74886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  return instance.Reallocate(p, size, stack);
74986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
75086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
75186277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid *asan_valloc(uptr size, BufferedStackTrace *stack) {
75286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  return instance.Allocate(size, GetPageSizeCached(), stack, FROM_MALLOC, true);
75386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
75486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
75586277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid *asan_pvalloc(uptr size, BufferedStackTrace *stack) {
75686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  uptr PageSize = GetPageSizeCached();
75786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  size = RoundUpTo(size, PageSize);
75886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  if (size == 0) {
75986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    // pvalloc(0) should allocate one page.
76086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    size = PageSize;
76186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  }
76286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  return instance.Allocate(size, PageSize, stack, FROM_MALLOC, true);
76386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
76486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
76586277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesint asan_posix_memalign(void **memptr, uptr alignment, uptr size,
76686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines                        BufferedStackTrace *stack) {
76786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  void *ptr = instance.Allocate(size, alignment, stack, FROM_MALLOC, true);
76886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  CHECK(IsAligned((uptr)ptr, alignment));
76986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  *memptr = ptr;
77086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  return 0;
77186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
77286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
773c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainaruptr asan_malloc_usable_size(const void *ptr, uptr pc, uptr bp) {
774799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  if (!ptr) return 0;
77586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  uptr usable_size = instance.AllocationSize(reinterpret_cast<uptr>(ptr));
77686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  if (flags()->check_malloc_usable_size && (usable_size == 0)) {
77786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    GET_STACK_TRACE_FATAL(pc, bp);
77886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    ReportMallocUsableSizeNotOwned((uptr)ptr, &stack);
77986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  }
78086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  return usable_size;
78186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
78286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
78386277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesuptr asan_mz_size(const void *ptr) {
78486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  return instance.AllocationSize(reinterpret_cast<uptr>(ptr));
78586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
78686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
78786277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid asan_mz_force_lock() {
78886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  instance.ForceLock();
78986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
79086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
79186277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid asan_mz_force_unlock() {
79286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  instance.ForceUnlock();
79386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
79486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
79586277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid AsanSoftRssLimitExceededCallback(bool exceeded) {
79686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  instance.allocator.SetRssLimitIsExceeded(exceeded);
79786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
79886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
799799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar} // namespace __asan
80086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
80186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// --- Implementation of LSan-specific functions --- {{{1
80286277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesnamespace __lsan {
80386277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid LockAllocator() {
80486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  __asan::get_allocator().ForceLock();
80586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
80686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
80786277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid UnlockAllocator() {
80886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  __asan::get_allocator().ForceUnlock();
80986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
81086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
81186277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid GetAllocatorGlobalRange(uptr *begin, uptr *end) {
81286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  *begin = (uptr)&__asan::get_allocator();
81386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  *end = *begin + sizeof(__asan::get_allocator());
81486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
81586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
81686277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesuptr PointsIntoChunk(void* p) {
81786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  uptr addr = reinterpret_cast<uptr>(p);
81886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  __asan::AsanChunk *m = __asan::instance.GetAsanChunkByAddrFastLocked(addr);
81986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  if (!m) return 0;
82086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  uptr chunk = m->Beg();
82186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  if (m->chunk_state != __asan::CHUNK_ALLOCATED)
82286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    return 0;
82386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  if (m->AddrIsInside(addr, /*locked_version=*/true))
82486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    return chunk;
82586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  if (IsSpecialCaseOfOperatorNew0(chunk, m->UsedSize(/*locked_version*/ true),
82686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines                                  addr))
82786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    return chunk;
82886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  return 0;
82986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
83086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
83186277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesuptr GetUserBegin(uptr chunk) {
83286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  __asan::AsanChunk *m = __asan::instance.GetAsanChunkByAddrFastLocked(chunk);
83386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  CHECK(m);
83486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  return m->Beg();
83586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
83686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
83786277eb844c4983c81de62d7c050e92fe7155788Stephen HinesLsanMetadata::LsanMetadata(uptr chunk) {
83886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  metadata_ = reinterpret_cast<void *>(chunk - __asan::kChunkHeaderSize);
83986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
84086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
84186277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesbool LsanMetadata::allocated() const {
84286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  __asan::AsanChunk *m = reinterpret_cast<__asan::AsanChunk *>(metadata_);
84386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  return m->chunk_state == __asan::CHUNK_ALLOCATED;
84486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
84586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
84686277eb844c4983c81de62d7c050e92fe7155788Stephen HinesChunkTag LsanMetadata::tag() const {
84786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  __asan::AsanChunk *m = reinterpret_cast<__asan::AsanChunk *>(metadata_);
84886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  return static_cast<ChunkTag>(m->lsan_tag);
84986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
85086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
85186277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid LsanMetadata::set_tag(ChunkTag value) {
85286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  __asan::AsanChunk *m = reinterpret_cast<__asan::AsanChunk *>(metadata_);
85386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  m->lsan_tag = value;
85486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
85586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
85686277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesuptr LsanMetadata::requested_size() const {
85786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  __asan::AsanChunk *m = reinterpret_cast<__asan::AsanChunk *>(metadata_);
85886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  return m->UsedSize(/*locked_version=*/true);
85986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
86086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
86186277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesu32 LsanMetadata::stack_trace_id() const {
86286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  __asan::AsanChunk *m = reinterpret_cast<__asan::AsanChunk *>(metadata_);
86386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  return m->alloc_context_id;
86486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
86586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
86686277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid ForEachChunk(ForEachChunkCallback callback, void *arg) {
86786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  __asan::get_allocator().ForEachChunk(callback, arg);
86886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
86986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
87086277eb844c4983c81de62d7c050e92fe7155788Stephen HinesIgnoreObjectResult IgnoreObjectLocked(const void *p) {
87186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  uptr addr = reinterpret_cast<uptr>(p);
87286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  __asan::AsanChunk *m = __asan::instance.GetAsanChunkByAddr(addr);
87386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  if (!m) return kIgnoreObjectInvalid;
87486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  if ((m->chunk_state == __asan::CHUNK_ALLOCATED) && m->AddrIsInside(addr)) {
87586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    if (m->lsan_tag == kIgnored)
87686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines      return kIgnoreObjectAlreadyIgnored;
87786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    m->lsan_tag = __lsan::kIgnored;
87886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    return kIgnoreObjectSuccess;
87986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  } else {
88086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    return kIgnoreObjectInvalid;
88186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  }
88286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
88386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}  // namespace __lsan
88486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
88586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// ---------------------- Interface ---------------- {{{1
88686277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesusing namespace __asan;  // NOLINT
88786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
88886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// ASan allocator doesn't reserve extra bytes, so normally we would
88986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// just return "size". We don't want to expose our redzone sizes, etc here.
89086277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesuptr __sanitizer_get_estimated_allocated_size(uptr size) {
89186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  return size;
89286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
89386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
89486277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesint __sanitizer_get_ownership(const void *p) {
89586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  uptr ptr = reinterpret_cast<uptr>(p);
89686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  return instance.AllocationSize(ptr) > 0;
89786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
89886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
89986277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesuptr __sanitizer_get_allocated_size(const void *p) {
900799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar  if (!p) return 0;
90186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  uptr ptr = reinterpret_cast<uptr>(p);
90286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  uptr allocated_size = instance.AllocationSize(ptr);
90386277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // Die if p is not malloced or if it is already freed.
90486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  if (allocated_size == 0) {
90586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    GET_STACK_TRACE_FATAL_HERE;
90686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines    ReportSanitizerGetAllocatedSizeNotOwned(ptr, &stack);
90786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  }
90886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  return allocated_size;
90986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
91086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines
91186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#if !SANITIZER_SUPPORTS_WEAK_HOOKS
91286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines// Provide default (no-op) implementation of malloc hooks.
91386277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesextern "C" {
91486277eb844c4983c81de62d7c050e92fe7155788Stephen HinesSANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
91586277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid __sanitizer_malloc_hook(void *ptr, uptr size) {
91686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  (void)ptr;
91786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  (void)size;
91886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
91986277eb844c4983c81de62d7c050e92fe7155788Stephen HinesSANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
92086277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesvoid __sanitizer_free_hook(void *ptr) {
92186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  (void)ptr;
92286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines}
923799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar} // extern "C"
92486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#endif
925