asan_fake_stack.h revision b1173c27c2791aef27304e68911a11648401064d
1//===-- asan_fake_stack.h ---------------------------------------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file is a part of AddressSanitizer, an address sanity checker.
11//
12// ASan-private header for asan_fake_stack.cc, implements FakeStack.
13//===----------------------------------------------------------------------===//
14
15#ifndef ASAN_FAKE_STACK_H
16#define ASAN_FAKE_STACK_H
17
18#include "sanitizer_common/sanitizer_common.h"
19
20namespace __asan {
21
22// Fake stack frame contains local variables of one function.
23struct FakeFrame {
24  uptr magic;  // Modified by the instrumented code.
25  uptr descr;  // Modified by the instrumented code.
26  uptr pc;     // Modified by the instrumented code.
27  u64 real_stack : 48;
28  u64 class_id : 16;
29};
30
31// For each thread we create a fake stack and place stack objects on this fake
32// stack instead of the real stack. The fake stack is not really a stack but
33// a fast malloc-like allocator so that when a function exits the fake stack
34// is not popped but remains there for quite some time until gets used again.
35// So, we poison the objects on the fake stack when function returns.
36// It helps us find use-after-return bugs.
37//
38// The FakeStack objects is allocated by a single mmap call and has no other
39// pointers. The size of the fake stack depends on the actual thread stack size
40// and thus can not be a constant.
41// stack_size is a power of two greater or equal to the thread's stack size;
42// we store it as its logarithm (stack_size_log).
43// FakeStack has kNumberOfSizeClasses (11) size classes, each size class
44// is a power of two, starting from 64 bytes. Each size class occupies
45// stack_size bytes and thus can allocate
46// NumberOfFrames=(stack_size/BytesInSizeClass) fake frames (also a power of 2).
47// For each size class we have NumberOfFrames allocation flags,
48// each flag indicates whether the given frame is currently allocated.
49// All flags for size classes 0 .. 10 are stored in a single contiguous region
50// followed by another contiguous region which contains the actual memory for
51// size classes. The addresses are computed by GetFlags and GetFrame without
52// any memory accesses solely based on 'this' and stack_size_log.
53// Allocate() flips the appropriate allocation flag atomically, thus achieving
54// async-signal safety.
55// This allocator does not have quarantine per se, but it tries to allocate the
56// frames in round robin fasion to maximize the delay between a deallocation
57// and the next allocation.
58class FakeStack {
59  static const uptr kMinStackFrameSizeLog = 6;  // Min frame is 64B.
60  static const uptr kMaxStackFrameSizeLog = 16;  // Max stack frame is 64K.
61
62 public:
63  static const uptr kNumberOfSizeClasses =
64       kMaxStackFrameSizeLog - kMinStackFrameSizeLog + 1;
65
66  // CTOR: create the FakeStack as a single mmap-ed object.
67  static FakeStack *Create(uptr stack_size_log) {
68    static uptr kMinStackSizeLog = 16;
69    static uptr kMaxStackSizeLog = FIRST_32_SECOND_64(23, 26);
70    if (stack_size_log < kMinStackSizeLog)
71      stack_size_log = kMinStackSizeLog;
72    if (stack_size_log > kMaxStackSizeLog)
73      stack_size_log = kMaxStackSizeLog;
74    FakeStack *res = reinterpret_cast<FakeStack *>(
75        MmapOrDie(RequiredSize(stack_size_log), "FakeStack"));
76    res->stack_size_log_ = stack_size_log;
77    return res;
78  }
79
80  void Destroy() {
81    UnmapOrDie(this, RequiredSize(stack_size_log_));
82  }
83
84  // stack_size_log is at least 15 (stack_size >= 32K).
85  static uptr SizeRequiredForFlags(uptr stack_size_log) {
86    return 1UL << (stack_size_log + 1 - kMinStackFrameSizeLog);
87  }
88
89  // Each size class occupies stack_size bytes.
90  static uptr SizeRequiredForFrames(uptr stack_size_log) {
91    return (1ULL << stack_size_log) * kNumberOfSizeClasses;
92  }
93
94  // Number of bytes requires for the whole object.
95  static uptr RequiredSize(uptr stack_size_log) {
96    return kFlagsOffset + SizeRequiredForFlags(stack_size_log) +
97           SizeRequiredForFrames(stack_size_log);
98  }
99
100  // Offset of the given flag from the first flag.
101  // The flags for class 0 begin at offset  000000000
102  // The flags for class 1 begin at offset  100000000
103  // ....................2................  110000000
104  // ....................3................  111000000
105  // and so on.
106  static uptr FlagsOffset(uptr stack_size_log, uptr class_id) {
107    uptr t = kNumberOfSizeClasses - 1 - class_id;
108    const uptr all_ones = (1 << (kNumberOfSizeClasses - 1)) - 1;
109    return ((all_ones >> t) << t) << (stack_size_log - 15);
110  }
111
112  static uptr NumberOfFrames(uptr stack_size_log, uptr class_id) {
113    return 1UL << (stack_size_log - kMinStackFrameSizeLog - class_id);
114  }
115
116  // Divide n by the numbe of frames in size class.
117  static uptr ModuloNumberOfFrames(uptr stack_size_log, uptr class_id, uptr n) {
118    return n & (NumberOfFrames(stack_size_log, class_id) - 1);
119  }
120
121  // The the pointer to the flags of the given class_id.
122  u8 *GetFlags(uptr stack_size_log, uptr class_id) {
123    return reinterpret_cast<u8 *>(this) + kFlagsOffset +
124           FlagsOffset(stack_size_log, class_id);
125  }
126
127  // Get frame by class_id and pos.
128  u8 *GetFrame(uptr stack_size_log, uptr class_id, uptr pos) {
129    return reinterpret_cast<u8 *>(this) + kFlagsOffset +
130           SizeRequiredForFlags(stack_size_log) +
131           (1 << stack_size_log) * class_id + BytesInSizeClass(class_id) * pos;
132  }
133
134  // Allocate the fake frame.
135  FakeFrame *Allocate(uptr stack_size_log, uptr class_id, uptr real_stack);
136
137  // Deallocate the fake frame.
138  void Deallocate(FakeFrame *ff, uptr stack_size_log, uptr class_id,
139                  uptr real_stack);
140
141  // Poison the entire FakeStack's shadow with the magic value.
142  void PoisonAll(u8 magic);
143
144  // Return the beginning of the FakeFrame or 0 if the address is not ours.
145  uptr AddrIsInFakeStack(uptr addr);
146
147  // Number of bytes in a fake frame of this size class.
148  static uptr BytesInSizeClass(uptr class_id) {
149    return 1UL << (class_id + kMinStackFrameSizeLog);
150  }
151
152  uptr stack_size_log() const { return stack_size_log_; }
153
154  void HandleNoReturn();
155  void GC(uptr real_stack);
156
157 private:
158  FakeStack() { }
159  static const uptr kFlagsOffset = 4096;  // This is were the flags begin.
160  // Must match the number of uses of DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID
161  COMPILER_CHECK(kNumberOfSizeClasses == 11);
162  static const uptr kMaxStackMallocSize = 1 << kMaxStackFrameSizeLog;
163
164  uptr hint_position_[kNumberOfSizeClasses];
165  uptr stack_size_log_;
166  // a bit is set if something was allocated from the corresponding size class.
167  uptr allocated_from_size_class_mask_;
168  bool needs_gc_;
169};
170
171}  // namespace __asan
172
173#endif  // ASAN_FAKE_STACK_H
174