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