11e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//===-- asan_allocator.h ----------------------------------------*- C++ -*-===// 21e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 31e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// The LLVM Compiler Infrastructure 41e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 51e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// This file is distributed under the University of Illinois Open Source 61e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// License. See LICENSE.TXT for details. 71e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 81e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//===----------------------------------------------------------------------===// 91e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 101e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// This file is a part of AddressSanitizer, an address sanity checker. 111e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 121e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// ASan-private header for asan_allocator.cc. 131e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//===----------------------------------------------------------------------===// 141e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 151e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#ifndef ASAN_ALLOCATOR_H 161e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#define ASAN_ALLOCATOR_H 171e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 181e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_internal.h" 191e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_interceptors.h" 201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanynamespace __asan { 221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 233f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryanystatic const uptr kNumberOfSizeClasses = 255; 24cbab911ea555f34c8ac66b4c7dc88f4e7ecf2c03Kostya Serebryanystruct AsanChunk; 251e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 261e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyclass AsanChunkFifoList { 271e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany public: 281e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany explicit AsanChunkFifoList(LinkerInitialized) { } 291e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany AsanChunkFifoList() { clear(); } 301e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany void Push(AsanChunk *n); 311e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany void PushList(AsanChunkFifoList *q); 321e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany AsanChunk *Pop(); 333f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany uptr size() { return size_; } 341e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany void clear() { 353f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany first_ = last_ = 0; 361e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany size_ = 0; 371e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 381e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany private: 391e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany AsanChunk *first_; 401e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany AsanChunk *last_; 413f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany uptr size_; 421e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}; 431e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 441e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanystruct AsanThreadLocalMallocStorage { 451e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany explicit AsanThreadLocalMallocStorage(LinkerInitialized x) 461e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany : quarantine_(x) { } 471e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany AsanThreadLocalMallocStorage() { 4809672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov CHECK(REAL(memset)); 4909672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov REAL(memset)(this, 0, sizeof(AsanThreadLocalMallocStorage)); 501e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 511e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 521e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany AsanChunkFifoList quarantine_; 531e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany AsanChunk *free_lists_[kNumberOfSizeClasses]; 541e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany void CommitBack(); 551e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}; 561e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 571e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Fake stack frame contains local variables of one function. 581e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// This struct should fit into a stack redzone (32 bytes). 591e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanystruct FakeFrame { 603f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany uptr magic; // Modified by the instrumented code. 613f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany uptr descr; // Modified by the instrumented code. 621e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany FakeFrame *next; 63ee3925515e4c7966f3ef489f687aa7e5692806a9Kostya Serebryany u64 real_stack : 48; 64ee3925515e4c7966f3ef489f687aa7e5692806a9Kostya Serebryany u64 size_minus_one : 16; 651e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}; 661e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 671e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanystruct FakeFrameFifo { 681e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany public: 691e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany void FifoPush(FakeFrame *node); 701e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany FakeFrame *FifoPop(); 711e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany private: 721e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany FakeFrame *first_, *last_; 731e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}; 741e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 751e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyclass FakeFrameLifo { 761e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany public: 771e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany void LifoPush(FakeFrame *node) { 781e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany node->next = top_; 791e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany top_ = node; 801e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 811e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany void LifoPop() { 821e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany CHECK(top_); 831e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany top_ = top_->next; 841e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 851e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany FakeFrame *top() { return top_; } 861e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany private: 871e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany FakeFrame *top_; 881e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}; 891e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 901e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// For each thread we create a fake stack and place stack objects on this fake 911e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// stack instead of the real stack. The fake stack is not really a stack but 921e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// a fast malloc-like allocator so that when a function exits the fake stack 931e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// is not poped but remains there for quite some time until gets used again. 941e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// So, we poison the objects on the fake stack when function returns. 951e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// It helps us find use-after-return bugs. 961e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// We can not rely on __asan_stack_free being called on every function exit, 971e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// so we maintain a lifo list of all current fake frames and update it on every 981e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// call to __asan_stack_malloc. 991e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyclass FakeStack { 1001e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany public: 1011e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany FakeStack(); 1021e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany explicit FakeStack(LinkerInitialized) {} 1033f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany void Init(uptr stack_size); 104c4b34d9af5a7849f91b9a9ba418a2bd144b0812bKostya Serebryany void StopUsingFakeStack() { alive_ = false; } 1051e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany void Cleanup(); 1063f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany uptr AllocateStack(uptr size, uptr real_stack); 1073f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany static void OnFree(uptr ptr, uptr size, uptr real_stack); 1081e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // Return the bottom of the maped region. 1093f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany uptr AddrIsInFakeStack(uptr addr); 11060490e08cce301b2dd7b72fcae8e20ef58c89a9bAlexander Potapenko bool StackSize() { return stack_size_; } 1115092682c3a6902e460a6e439cf48b3dc7d48dc65Alexey Samsonov 1121e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany private: 1133f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany static const uptr kMinStackFrameSizeLog = 9; // Min frame is 512B. 1143f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany static const uptr kMaxStackFrameSizeLog = 16; // Max stack frame is 64K. 1153f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany static const uptr kMaxStackMallocSize = 1 << kMaxStackFrameSizeLog; 1163f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany static const uptr kNumberOfSizeClasses = 1171e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany kMaxStackFrameSizeLog - kMinStackFrameSizeLog + 1; 1181e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 1193f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany bool AddrIsInSizeClass(uptr addr, uptr size_class); 1201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 1211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // Each size class should be large enough to hold all frames. 1223f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany uptr ClassMmapSize(uptr size_class); 1231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 1243f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany uptr ClassSize(uptr size_class) { 1251e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return 1UL << (size_class + kMinStackFrameSizeLog); 1261e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 1271e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 1281e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany void DeallocateFrame(FakeFrame *fake_frame); 1291e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 1303f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany uptr ComputeSizeClass(uptr alloc_size); 1313f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany void AllocateOneSizeClass(uptr size_class); 1321e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 1333f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany uptr stack_size_; 1341e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany bool alive_; 1351e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 1363f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany uptr allocated_size_classes_[kNumberOfSizeClasses]; 1371e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany FakeFrameFifo size_classes_[kNumberOfSizeClasses]; 1381e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany FakeFrameLifo call_stack_; 1391e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}; 1401e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 141c3390df6670cb166119b961eb27a033fb9073496Kostya Serebryanyvoid *asan_memalign(uptr alignment, uptr size, StackTrace *stack); 142c3390df6670cb166119b961eb27a033fb9073496Kostya Serebryanyvoid asan_free(void *ptr, StackTrace *stack); 1431e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 144c3390df6670cb166119b961eb27a033fb9073496Kostya Serebryanyvoid *asan_malloc(uptr size, StackTrace *stack); 145c3390df6670cb166119b961eb27a033fb9073496Kostya Serebryanyvoid *asan_calloc(uptr nmemb, uptr size, StackTrace *stack); 146c3390df6670cb166119b961eb27a033fb9073496Kostya Serebryanyvoid *asan_realloc(void *p, uptr size, StackTrace *stack); 147c3390df6670cb166119b961eb27a033fb9073496Kostya Serebryanyvoid *asan_valloc(uptr size, StackTrace *stack); 148c3390df6670cb166119b961eb27a033fb9073496Kostya Serebryanyvoid *asan_pvalloc(uptr size, StackTrace *stack); 1491e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 1503f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryanyint asan_posix_memalign(void **memptr, uptr alignment, uptr size, 151c3390df6670cb166119b961eb27a033fb9073496Kostya Serebryany StackTrace *stack); 152c3390df6670cb166119b961eb27a033fb9073496Kostya Serebryanyuptr asan_malloc_usable_size(void *ptr, StackTrace *stack); 1531e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 1543f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryanyuptr asan_mz_size(const void *ptr); 1554fd95f141f78906570c15a8a3b4cf0a7b50a201dAlexey Samsonovvoid asan_mz_force_lock(); 1564fd95f141f78906570c15a8a3b4cf0a7b50a201dAlexey Samsonovvoid asan_mz_force_unlock(); 1571e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 1581e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} // namespace __asan 1591e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#endif // ASAN_ALLOCATOR_H 160