asan_fake_stack.h revision 89de457bd3ec40d38bc7860f88f1d4da473eacc4
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.
58//
59// FIXME: handle throw/longjmp/clone, i.e. garbage collect the unwinded frames.
60class FakeStack {
61  static const uptr kMinStackFrameSizeLog = 6;  // Min frame is 64B.
62  static const uptr kMaxStackFrameSizeLog = 16;  // Max stack frame is 64K.
63
64 public:
65  static const uptr kNumberOfSizeClasses =
66       kMaxStackFrameSizeLog - kMinStackFrameSizeLog + 1;
67
68  // CTOR: create the FakeStack as a single mmap-ed object.
69  static FakeStack *Create(uptr stack_size_log) {
70    static uptr kMinStackSizeLog = 16;
71    static uptr kMaxStackSizeLog = FIRST_32_SECOND_64(23, 26);
72    if (stack_size_log < kMinStackSizeLog)
73      stack_size_log = kMinStackSizeLog;
74    if (stack_size_log > kMaxStackSizeLog)
75      stack_size_log = kMaxStackSizeLog;
76    FakeStack *res = reinterpret_cast<FakeStack *>(
77        MmapOrDie(RequiredSize(stack_size_log), "FakeStack"));
78    res->stack_size_log_ = stack_size_log;
79    return res;
80  }
81
82  void Destroy() {
83    UnmapOrDie(this, RequiredSize(stack_size_log_));
84  }
85
86  // stack_size_log is at least 15 (stack_size >= 32K).
87  static uptr SizeRequiredForFlags(uptr stack_size_log) {
88    return 1UL << (stack_size_log + 1 - kMinStackFrameSizeLog);
89  }
90
91  // Each size class occupies stack_size bytes.
92  static uptr SizeRequiredForFrames(uptr stack_size_log) {
93    return (1ULL << stack_size_log) * kNumberOfSizeClasses;
94  }
95
96  // Number of bytes requires for the whole object.
97  static uptr RequiredSize(uptr stack_size_log) {
98    return kFlagsOffset + SizeRequiredForFlags(stack_size_log) +
99           SizeRequiredForFrames(stack_size_log);
100  }
101
102  // Offset of the given flag from the first flag.
103  // The flags for class 0 begin at offset  000000000
104  // The flags for class 1 begin at offset  100000000
105  // ....................2................  110000000
106  // ....................3................  111000000
107  // and so on.
108  static uptr FlagsOffset(uptr stack_size_log, uptr class_id) {
109    uptr t = kNumberOfSizeClasses - 1 - class_id;
110    const uptr all_ones = (1 << (kNumberOfSizeClasses - 1)) - 1;
111    return ((all_ones >> t) << t) << (stack_size_log - 15);
112  }
113
114  static uptr NumberOfFrames(uptr stack_size_log, uptr class_id) {
115    return 1UL << (stack_size_log - kMinStackFrameSizeLog - class_id);
116  }
117
118  // Divide n by the numbe of frames in size class.
119  static uptr ModuloNumberOfFrames(uptr stack_size_log, uptr class_id, uptr n) {
120    return n & (NumberOfFrames(stack_size_log, class_id) - 1);
121  }
122
123  // The the pointer to the flags of the given class_id.
124  u8 *GetFlags(uptr stack_size_log, uptr class_id) {
125    return reinterpret_cast<u8 *>(this) + kFlagsOffset +
126           FlagsOffset(stack_size_log, class_id);
127  }
128
129  // Get frame by class_id and pos.
130  u8 *GetFrame(uptr stack_size_log, uptr class_id, uptr pos) {
131    return reinterpret_cast<u8 *>(this) + kFlagsOffset +
132           SizeRequiredForFlags(stack_size_log) +
133           (1 << stack_size_log) * class_id + BytesInSizeClass(class_id) * pos;
134  }
135
136  // Allocate the fake frame.
137  FakeFrame *Allocate(uptr stack_size_log, uptr class_id, uptr real_stack);
138
139  // Deallocate the fake frame.
140  void Deallocate(FakeFrame *ff, uptr stack_size_log, uptr class_id,
141                  uptr real_stack);
142
143  // Poison the entire FakeStack's shadow with the magic value.
144  void PoisonAll(u8 magic);
145
146  // Return the beginning of the FakeFrame or 0 if the address is not ours.
147  uptr AddrIsInFakeStack(uptr addr);
148
149  // Number of bytes in a fake frame of this size class.
150  static uptr BytesInSizeClass(uptr class_id) {
151    return 1UL << (class_id + kMinStackFrameSizeLog);
152  }
153
154  uptr stack_size_log() const { return stack_size_log_; }
155
156  void HandleNoReturn();
157  void GC(uptr real_stack);
158
159 private:
160  FakeStack() { }
161  static const uptr kFlagsOffset = 4096;  // This is were the flags begin.
162  // Must match the number of uses of DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID
163  COMPILER_CHECK(kNumberOfSizeClasses == 11);
164  static const uptr kMaxStackMallocSize = 1 << kMaxStackFrameSizeLog;
165
166  uptr hint_position_[kNumberOfSizeClasses];
167  uptr stack_size_log_;
168  // a bit is set if something was allocated from the corresponding size class.
169  uptr allocated_from_size_class_mask_;
170  bool needs_gc_;
171};
172
173}  // namespace __asan
174
175#endif  // ASAN_FAKE_STACK_H
176