asan_allocator.h revision 276851
1251881Speter//===-- asan_allocator.h ----------------------------------------*- C++ -*-===//
2251881Speter//
3251881Speter//                     The LLVM Compiler Infrastructure
4251881Speter//
5251881Speter// This file is distributed under the University of Illinois Open Source
6251881Speter// License. See LICENSE.TXT for details.
7251881Speter//
8251881Speter//===----------------------------------------------------------------------===//
9251881Speter//
10251881Speter// This file is a part of AddressSanitizer, an address sanity checker.
11251881Speter//
12251881Speter// ASan-private header for asan_allocator2.cc.
13251881Speter//===----------------------------------------------------------------------===//
14251881Speter
15251881Speter#ifndef ASAN_ALLOCATOR_H
16251881Speter#define ASAN_ALLOCATOR_H
17251881Speter
18251881Speter#include "asan_internal.h"
19251881Speter#include "asan_interceptors.h"
20251881Speter#include "sanitizer_common/sanitizer_allocator.h"
21251881Speter#include "sanitizer_common/sanitizer_list.h"
22251881Speter
23251881Speternamespace __asan {
24251881Speter
25251881Speterenum AllocType {
26251881Speter  FROM_MALLOC = 1,  // Memory block came from malloc, calloc, realloc, etc.
27251881Speter  FROM_NEW = 2,     // Memory block came from operator new.
28251881Speter  FROM_NEW_BR = 3   // Memory block came from operator new [ ]
29251881Speter};
30251881Speter
31251881Speterstatic const uptr kNumberOfSizeClasses = 255;
32251881Speterstruct AsanChunk;
33251881Speter
34251881Spetervoid InitializeAllocator();
35251881Spetervoid ReInitializeAllocator();
36251881Speter
37251881Speterclass AsanChunkView {
38251881Speter public:
39251881Speter  explicit AsanChunkView(AsanChunk *chunk) : chunk_(chunk) {}
40251881Speter  bool IsValid();   // Checks if AsanChunkView points to a valid allocated
41251881Speter                    // or quarantined chunk.
42251881Speter  uptr Beg();       // First byte of user memory.
43251881Speter  uptr End();       // Last byte of user memory.
44251881Speter  uptr UsedSize();  // Size requested by the user.
45251881Speter  uptr AllocTid();
46251881Speter  uptr FreeTid();
47251881Speter  bool Eq(const AsanChunkView &c) const { return chunk_ == c.chunk_; }
48251881Speter  StackTrace GetAllocStack();
49251881Speter  StackTrace GetFreeStack();
50251881Speter  bool AddrIsInside(uptr addr, uptr access_size, sptr *offset) {
51251881Speter    if (addr >= Beg() && (addr + access_size) <= End()) {
52251881Speter      *offset = addr - Beg();
53251881Speter      return true;
54251881Speter    }
55251881Speter    return false;
56251881Speter  }
57251881Speter  bool AddrIsAtLeft(uptr addr, uptr access_size, sptr *offset) {
58251881Speter    (void)access_size;
59251881Speter    if (addr < Beg()) {
60251881Speter      *offset = Beg() - addr;
61251881Speter      return true;
62251881Speter    }
63251881Speter    return false;
64251881Speter  }
65251881Speter  bool AddrIsAtRight(uptr addr, uptr access_size, sptr *offset) {
66251881Speter    if (addr + access_size > End()) {
67251881Speter      *offset = addr - End();
68251881Speter      return true;
69251881Speter    }
70251881Speter    return false;
71251881Speter  }
72251881Speter
73251881Speter private:
74251881Speter  AsanChunk *const chunk_;
75251881Speter};
76251881Speter
77251881SpeterAsanChunkView FindHeapChunkByAddress(uptr address);
78251881Speter
79251881Speter// List of AsanChunks with total size.
80251881Speterclass AsanChunkFifoList: public IntrusiveList<AsanChunk> {
81251881Speter public:
82251881Speter  explicit AsanChunkFifoList(LinkerInitialized) { }
83251881Speter  AsanChunkFifoList() { clear(); }
84251881Speter  void Push(AsanChunk *n);
85251881Speter  void PushList(AsanChunkFifoList *q);
86251881Speter  AsanChunk *Pop();
87251881Speter  uptr size() { return size_; }
88251881Speter  void clear() {
89251881Speter    IntrusiveList<AsanChunk>::clear();
90251881Speter    size_ = 0;
91251881Speter  }
92251881Speter private:
93251881Speter  uptr size_;
94251881Speter};
95251881Speter
96251881Speterstruct AsanMapUnmapCallback {
97251881Speter  void OnMap(uptr p, uptr size) const;
98251881Speter  void OnUnmap(uptr p, uptr size) const;
99299742Sdim};
100251881Speter
101251881Speter#if SANITIZER_CAN_USE_ALLOCATOR64
102251881Speter# if defined(__powerpc64__)
103251881Speterconst uptr kAllocatorSpace =  0xa0000000000ULL;
104251881Speterconst uptr kAllocatorSize  =  0x20000000000ULL;  // 2T.
105251881Speter# else
106251881Speterconst uptr kAllocatorSpace = 0x600000000000ULL;
107251881Speterconst uptr kAllocatorSize  =  0x40000000000ULL;  // 4T.
108299742Sdim# endif
109251881Spetertypedef DefaultSizeClassMap SizeClassMap;
110251881Spetertypedef SizeClassAllocator64<kAllocatorSpace, kAllocatorSize, 0 /*metadata*/,
111251881Speter    SizeClassMap, AsanMapUnmapCallback> PrimaryAllocator;
112251881Speter#else  // Fallback to SizeClassAllocator32.
113251881Speterstatic const uptr kRegionSizeLog = 20;
114251881Speterstatic const uptr kNumRegions = SANITIZER_MMAP_RANGE_SIZE >> kRegionSizeLog;
115299742Sdim# if SANITIZER_WORDSIZE == 32
116299742Sdimtypedef FlatByteMap<kNumRegions> ByteMap;
117299742Sdim# elif SANITIZER_WORDSIZE == 64
118299742Sdimtypedef TwoLevelByteMap<(kNumRegions >> 12), 1 << 12> ByteMap;
119299742Sdim# endif
120299742Sdimtypedef CompactSizeClassMap SizeClassMap;
121299742Sdimtypedef SizeClassAllocator32<0, SANITIZER_MMAP_RANGE_SIZE, 16,
122299742Sdim  SizeClassMap, kRegionSizeLog,
123299742Sdim  ByteMap,
124299742Sdim  AsanMapUnmapCallback> PrimaryAllocator;
125299742Sdim#endif  // SANITIZER_CAN_USE_ALLOCATOR64
126299742Sdim
127299742Sdimtypedef SizeClassAllocatorLocalCache<PrimaryAllocator> AllocatorCache;
128299742Sdimtypedef LargeMmapAllocator<AsanMapUnmapCallback> SecondaryAllocator;
129299742Sdimtypedef CombinedAllocator<PrimaryAllocator, AllocatorCache,
130299742Sdim    SecondaryAllocator> Allocator;
131251881Speter
132299742Sdim
133299742Sdimstruct AsanThreadLocalMallocStorage {
134299742Sdim  uptr quarantine_cache[16];
135299742Sdim  AllocatorCache allocator2_cache;
136299742Sdim  void CommitBack();
137299742Sdim private:
138299742Sdim  // These objects are allocated via mmap() and are zero-initialized.
139299742Sdim  AsanThreadLocalMallocStorage() {}
140299742Sdim};
141299742Sdim
142299742Sdimvoid *asan_memalign(uptr alignment, uptr size, BufferedStackTrace *stack,
143299742Sdim                    AllocType alloc_type);
144299742Sdimvoid asan_free(void *ptr, BufferedStackTrace *stack, AllocType alloc_type);
145299742Sdimvoid asan_sized_free(void *ptr, uptr size, BufferedStackTrace *stack,
146299742Sdim                     AllocType alloc_type);
147299742Sdim
148299742Sdimvoid *asan_malloc(uptr size, BufferedStackTrace *stack);
149299742Sdimvoid *asan_calloc(uptr nmemb, uptr size, BufferedStackTrace *stack);
150299742Sdimvoid *asan_realloc(void *p, uptr size, BufferedStackTrace *stack);
151299742Sdimvoid *asan_valloc(uptr size, BufferedStackTrace *stack);
152251881Spetervoid *asan_pvalloc(uptr size, BufferedStackTrace *stack);
153251881Speter
154251881Speterint asan_posix_memalign(void **memptr, uptr alignment, uptr size,
155251881Speter                        BufferedStackTrace *stack);
156251881Speteruptr asan_malloc_usable_size(void *ptr, uptr pc, uptr bp);
157251881Speter
158251881Speteruptr asan_mz_size(const void *ptr);
159251881Spetervoid asan_mz_force_lock();
160299742Sdimvoid asan_mz_force_unlock();
161299742Sdim
162299742Sdimvoid PrintInternalAllocatorStats();
163299742Sdim
164299742Sdim}  // namespace __asan
165251881Speter#endif  // ASAN_ALLOCATOR_H
166251881Speter