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