1244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany//===-- asan_fake_stack.h ---------------------------------------*- C++ -*-===// 2244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany// 3244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany// The LLVM Compiler Infrastructure 4244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany// 5244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany// This file is distributed under the University of Illinois Open Source 6244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany// License. See LICENSE.TXT for details. 7244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany// 8244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany//===----------------------------------------------------------------------===// 9244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany// 10244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany// This file is a part of AddressSanitizer, an address sanity checker. 11244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany// 12244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany// ASan-private header for asan_fake_stack.cc 13244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany//===----------------------------------------------------------------------===// 14244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany 15244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany#ifndef ASAN_FAKE_STACK_H 16244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany#define ASAN_FAKE_STACK_H 17244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany 18244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryanynamespace __asan { 19244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany 20244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany// Fake stack frame contains local variables of one function. 21244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryanystruct FakeFrame { 22244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany uptr magic; // Modified by the instrumented code. 23244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany uptr descr; // Modified by the instrumented code. 24ce0f7d13a6d2f1c141bc247aa75770cb88b38cb6Kostya Serebryany uptr pc; // Modified by the instrumented code. 25244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany u64 real_stack : 48; 26244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany u64 size_minus_one : 16; 27ce0f7d13a6d2f1c141bc247aa75770cb88b38cb6Kostya Serebryany // End of the first 32 bytes. 28ce0f7d13a6d2f1c141bc247aa75770cb88b38cb6Kostya Serebryany // The rest should not be used when the frame is active. 29ce0f7d13a6d2f1c141bc247aa75770cb88b38cb6Kostya Serebryany FakeFrame *next; 30244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany}; 31244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany 32244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryanystruct FakeFrameFifo { 33244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany public: 34244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany void FifoPush(FakeFrame *node); 35244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany FakeFrame *FifoPop(); 36244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany private: 37244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany FakeFrame *first_, *last_; 38244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany}; 39244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany 40ce0f7d13a6d2f1c141bc247aa75770cb88b38cb6Kostya Serebryanytemplate<uptr kMaxNumberOfFrames> 41244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryanyclass FakeFrameLifo { 42244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany public: 43ce0f7d13a6d2f1c141bc247aa75770cb88b38cb6Kostya Serebryany explicit FakeFrameLifo(LinkerInitialized) {} 44ce0f7d13a6d2f1c141bc247aa75770cb88b38cb6Kostya Serebryany FakeFrameLifo() : n_frames_(0) {} 45244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany void LifoPush(FakeFrame *node) { 46ce0f7d13a6d2f1c141bc247aa75770cb88b38cb6Kostya Serebryany CHECK_LT(n_frames_, kMaxNumberOfFrames); 47ce0f7d13a6d2f1c141bc247aa75770cb88b38cb6Kostya Serebryany frames_[n_frames_++] = node; 48244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany } 49244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany void LifoPop() { 50ce0f7d13a6d2f1c141bc247aa75770cb88b38cb6Kostya Serebryany CHECK(n_frames_); 51ce0f7d13a6d2f1c141bc247aa75770cb88b38cb6Kostya Serebryany n_frames_--; 52ce0f7d13a6d2f1c141bc247aa75770cb88b38cb6Kostya Serebryany } 53ce0f7d13a6d2f1c141bc247aa75770cb88b38cb6Kostya Serebryany FakeFrame *top() { 54ce0f7d13a6d2f1c141bc247aa75770cb88b38cb6Kostya Serebryany if (n_frames_ == 0) 55ce0f7d13a6d2f1c141bc247aa75770cb88b38cb6Kostya Serebryany return 0; 5637f9464fc0fa4df2acf04264c52ba542d0e3d3fbKostya Serebryany return frames_[n_frames_ - 1]; 57244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany } 58244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany private: 59ce0f7d13a6d2f1c141bc247aa75770cb88b38cb6Kostya Serebryany uptr n_frames_; 60ce0f7d13a6d2f1c141bc247aa75770cb88b38cb6Kostya Serebryany FakeFrame *frames_[kMaxNumberOfFrames]; 61244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany}; 62244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany 63244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany// For each thread we create a fake stack and place stack objects on this fake 64244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany// stack instead of the real stack. The fake stack is not really a stack but 65244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany// a fast malloc-like allocator so that when a function exits the fake stack 66244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany// is not poped but remains there for quite some time until gets used again. 67244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany// So, we poison the objects on the fake stack when function returns. 68244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany// It helps us find use-after-return bugs. 69244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany// We can not rely on __asan_stack_free being called on every function exit, 70244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany// so we maintain a lifo list of all current fake frames and update it on every 71244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany// call to __asan_stack_malloc. 72244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryanyclass FakeStack { 73244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany public: 74244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany void Init(uptr stack_size); 75244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany void StopUsingFakeStack() { alive_ = false; } 76244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany void Cleanup(); 77244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany uptr AllocateStack(uptr size, uptr real_stack); 78244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany static void OnFree(uptr ptr, uptr size, uptr real_stack); 79244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany // Return the bottom of the maped region. 80244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany uptr AddrIsInFakeStack(uptr addr); 815e97ba38b00eb843a55189bb913b445cbe620894Timur Iskhodzhanov uptr StackSize() const { return stack_size_; } 82244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany 83244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany private: 84244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany static const uptr kMinStackFrameSizeLog = 9; // Min frame is 512B. 85244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany static const uptr kMaxStackFrameSizeLog = 16; // Max stack frame is 64K. 86244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany static const uptr kMaxStackMallocSize = 1 << kMaxStackFrameSizeLog; 87244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany static const uptr kNumberOfSizeClasses = 88244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany kMaxStackFrameSizeLog - kMinStackFrameSizeLog + 1; 897a0bba457ee05ced3adf37a0c0790d0ed23a5446Kostya Serebryany static const uptr kMaxRecursionDepth = 15000; 90244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany 91244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany bool AddrIsInSizeClass(uptr addr, uptr size_class); 92244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany 93244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany // Each size class should be large enough to hold all frames. 94244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany uptr ClassMmapSize(uptr size_class); 95244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany 96244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany uptr ClassSize(uptr size_class) { 97244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany return 1UL << (size_class + kMinStackFrameSizeLog); 98244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany } 99244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany 100244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany void DeallocateFrame(FakeFrame *fake_frame); 101244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany 102244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany uptr ComputeSizeClass(uptr alloc_size); 103244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany void AllocateOneSizeClass(uptr size_class); 104244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany 105244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany uptr stack_size_; 106244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany bool alive_; 107244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany 108244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany uptr allocated_size_classes_[kNumberOfSizeClasses]; 109244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany FakeFrameFifo size_classes_[kNumberOfSizeClasses]; 110ce0f7d13a6d2f1c141bc247aa75770cb88b38cb6Kostya Serebryany FakeFrameLifo<kMaxRecursionDepth> call_stack_; 111244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany}; 112244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany 1137a0bba457ee05ced3adf37a0c0790d0ed23a5446Kostya SerebryanyCOMPILER_CHECK(sizeof(FakeStack) <= (1 << 17)); 1147a0bba457ee05ced3adf37a0c0790d0ed23a5446Kostya Serebryany 115244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany} // namespace __asan 116244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany 117244384d1a8a518c0b1ceaa5809333a91db1104b6Kostya Serebryany#endif // ASAN_FAKE_STACK_H 118