asan_allocator.h revision e218beb2d14b663bd277158f386a86d0e62fef74
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===-- asan_allocator.h ----------------------------------------*- C++ -*-===// 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The LLVM Compiler Infrastructure 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file is distributed under the University of Illinois Open Source 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// License. See LICENSE.TXT for details. 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===// 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file is a part of AddressSanitizer, an address sanity checker. 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ASan-private header for asan_allocator.cc. 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===// 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef ASAN_ALLOCATOR_H 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define ASAN_ALLOCATOR_H 1790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "asan_internal.h" 1990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "asan_interceptors.h" 20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 2190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace __asan { 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const uptr kNumberOfSizeClasses = 255; 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct AsanChunk; 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class AsanChunkFifoList { 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 2890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) explicit AsanChunkFifoList(LinkerInitialized) { } 2990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) AsanChunkFifoList() { clear(); } 3090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) void Push(AsanChunk *n); 3190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) void PushList(AsanChunkFifoList *q); 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AsanChunk *Pop(); 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uptr size() { return size_; } 3490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) void clear() { 3590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) first_ = last_ = 0; 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_ = 0; 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) private: 3990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) AsanChunk *first_; 4090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) AsanChunk *last_; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uptr size_; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 4390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 4490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)struct AsanThreadLocalMallocStorage { 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit AsanThreadLocalMallocStorage(LinkerInitialized x) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : quarantine_(x) { } 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AsanThreadLocalMallocStorage() { 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(REAL(memset)); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) REAL(memset)(this, 0, sizeof(AsanThreadLocalMallocStorage)); 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AsanChunkFifoList quarantine_; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AsanChunk *free_lists_[kNumberOfSizeClasses]; 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void CommitBack(); 5590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}; 5690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 5790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Fake stack frame contains local variables of one function. 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This struct should fit into a stack redzone (32 bytes). 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct FakeFrame { 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uptr magic; // Modified by the instrumented code. 613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) uptr descr; // Modified by the instrumented code. 623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) FakeFrame *next; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u64 real_stack : 48; 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) u64 size_minus_one : 16; 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 6690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 67d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)struct FakeFrameFifo { 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void FifoPush(FakeFrame *node); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FakeFrame *FifoPop(); 7190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) private: 72d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) FakeFrame *first_, *last_; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class FakeFrameLifo { 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void LifoPush(FakeFrame *node) { 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node->next = top_; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) top_ = node; 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) void LifoPop() { 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(top_); 8368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) top_ = top_->next; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FakeFrame *top() { return top_; } 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 8790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) FakeFrame *top_; 88d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}; 89d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 90d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)// For each thread we create a fake stack and place stack objects on this fake 9190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// stack instead of the real stack. The fake stack is not really a stack but 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// a fast malloc-like allocator so that when a function exits the fake stack 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is not poped but remains there for quite some time until gets used again. 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// So, we poison the objects on the fake stack when function returns. 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// It helps us find use-after-return bugs. 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We can not rely on __asan_stack_free being called on every function exit, 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// so we maintain a lifo list of all current fake frames and update it on every 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// call to __asan_stack_malloc. 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class FakeStack { 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FakeStack(); 10290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) explicit FakeStack(LinkerInitialized) {} 10390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) void Init(uptr stack_size); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void StopUsingFakeStack() { alive_ = false; } 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Cleanup(); 10690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) uptr AllocateStack(uptr size, uptr real_stack); 10790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) static void OnFree(uptr ptr, uptr size, uptr real_stack); 10890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Return the bottom of the maped region. 10990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) uptr AddrIsInFakeStack(uptr addr); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool StackSize() { return stack_size_; } 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 11290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) static const uptr kMinStackFrameSizeLog = 9; // Min frame is 512B. 11390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) static const uptr kMaxStackFrameSizeLog = 16; // Max stack frame is 64K. 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const uptr kMaxStackMallocSize = 1 << kMaxStackFrameSizeLog; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const uptr kNumberOfSizeClasses = 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kMaxStackFrameSizeLog - kMinStackFrameSizeLog + 1; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool AddrIsInSizeClass(uptr addr, uptr size_class); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) // Each size class should be large enough to hold all frames. 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uptr ClassMmapSize(uptr size_class); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 123d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) uptr ClassSize(uptr size_class) { 12490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return 1UL << (size_class + kMinStackFrameSizeLog); 125d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) } 126d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void DeallocateFrame(FakeFrame *fake_frame); 12890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uptr ComputeSizeClass(uptr alloc_size); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void AllocateOneSizeClass(uptr size_class); 13190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uptr stack_size_; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool alive_; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) uptr allocated_size_classes_[kNumberOfSizeClasses]; 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FakeFrameFifo size_classes_[kNumberOfSizeClasses]; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FakeFrameLifo call_stack_; 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void *asan_memalign(uptr alignment, uptr size, AsanStackTrace *stack); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void asan_free(void *ptr, AsanStackTrace *stack); 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void *asan_malloc(uptr size, AsanStackTrace *stack); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void *asan_calloc(uptr nmemb, uptr size, AsanStackTrace *stack); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void *asan_realloc(void *p, uptr size, AsanStackTrace *stack); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void *asan_valloc(uptr size, AsanStackTrace *stack); 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void *asan_pvalloc(uptr size, AsanStackTrace *stack); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int asan_posix_memalign(void **memptr, uptr alignment, uptr size, 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AsanStackTrace *stack); 151d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)uptr asan_malloc_usable_size(void *ptr, AsanStackTrace *stack); 152d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uptr asan_mz_size(const void *ptr); 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void asan_mz_force_lock(); 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void asan_mz_force_unlock(); 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace __asan 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // ASAN_ALLOCATOR_H 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)