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)