12679f1904dc5d5eb2ce82014116764c5f5131a2bKostya Serebryany//===-- asan_fake_stack.cc ------------------------------------------------===//
22679f1904dc5d5eb2ce82014116764c5f5131a2bKostya Serebryany//
32679f1904dc5d5eb2ce82014116764c5f5131a2bKostya Serebryany//                     The LLVM Compiler Infrastructure
42679f1904dc5d5eb2ce82014116764c5f5131a2bKostya Serebryany//
52679f1904dc5d5eb2ce82014116764c5f5131a2bKostya Serebryany// This file is distributed under the University of Illinois Open Source
62679f1904dc5d5eb2ce82014116764c5f5131a2bKostya Serebryany// License. See LICENSE.TXT for details.
72679f1904dc5d5eb2ce82014116764c5f5131a2bKostya Serebryany//
82679f1904dc5d5eb2ce82014116764c5f5131a2bKostya Serebryany//===----------------------------------------------------------------------===//
92679f1904dc5d5eb2ce82014116764c5f5131a2bKostya Serebryany//
102679f1904dc5d5eb2ce82014116764c5f5131a2bKostya Serebryany// This file is a part of AddressSanitizer, an address sanity checker.
112679f1904dc5d5eb2ce82014116764c5f5131a2bKostya Serebryany//
122679f1904dc5d5eb2ce82014116764c5f5131a2bKostya Serebryany// FakeStack is used to detect use-after-return bugs.
132679f1904dc5d5eb2ce82014116764c5f5131a2bKostya Serebryany//===----------------------------------------------------------------------===//
142679f1904dc5d5eb2ce82014116764c5f5131a2bKostya Serebryany#include "asan_allocator.h"
157e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov#include "asan_poisoning.h"
162679f1904dc5d5eb2ce82014116764c5f5131a2bKostya Serebryany#include "asan_thread.h"
172679f1904dc5d5eb2ce82014116764c5f5131a2bKostya Serebryany
182679f1904dc5d5eb2ce82014116764c5f5131a2bKostya Serebryanynamespace __asan {
192679f1904dc5d5eb2ce82014116764c5f5131a2bKostya Serebryany
208f7ec32eb34fb051f22e10b228ac056f919c4284Kostya Serebryanystatic const u64 kMagic1 = kAsanStackAfterReturnMagic;
218f7ec32eb34fb051f22e10b228ac056f919c4284Kostya Serebryanystatic const u64 kMagic2 = (kMagic1 << 8) | kMagic1;
228f7ec32eb34fb051f22e10b228ac056f919c4284Kostya Serebryanystatic const u64 kMagic4 = (kMagic2 << 16) | kMagic2;
238f7ec32eb34fb051f22e10b228ac056f919c4284Kostya Serebryanystatic const u64 kMagic8 = (kMagic4 << 32) | kMagic4;
248f7ec32eb34fb051f22e10b228ac056f919c4284Kostya Serebryany
258f7ec32eb34fb051f22e10b228ac056f919c4284Kostya Serebryany// For small size classes inline PoisonShadow for better performance.
268f7ec32eb34fb051f22e10b228ac056f919c4284Kostya SerebryanyALWAYS_INLINE void SetShadow(uptr ptr, uptr size, uptr class_id, u64 magic) {
278f7ec32eb34fb051f22e10b228ac056f919c4284Kostya Serebryany  CHECK_EQ(SHADOW_SCALE, 3);  // This code expects SHADOW_SCALE=3.
288f7ec32eb34fb051f22e10b228ac056f919c4284Kostya Serebryany  u64 *shadow = reinterpret_cast<u64*>(MemToShadow(ptr));
298f7ec32eb34fb051f22e10b228ac056f919c4284Kostya Serebryany  if (class_id <= 6) {
30dff16d41223d2df3762ba64a0a529c5e475de34fKostya Serebryany    for (uptr i = 0; i < (1U << class_id); i++)
318f7ec32eb34fb051f22e10b228ac056f919c4284Kostya Serebryany      shadow[i] = magic;
328f7ec32eb34fb051f22e10b228ac056f919c4284Kostya Serebryany  } else {
338f7ec32eb34fb051f22e10b228ac056f919c4284Kostya Serebryany    // The size class is too big, it's cheaper to poison only size bytes.
34dff16d41223d2df3762ba64a0a529c5e475de34fKostya Serebryany    PoisonShadow(ptr, size, static_cast<u8>(magic));
358f7ec32eb34fb051f22e10b228ac056f919c4284Kostya Serebryany  }
368f7ec32eb34fb051f22e10b228ac056f919c4284Kostya Serebryany}
378f7ec32eb34fb051f22e10b228ac056f919c4284Kostya Serebryany
38e1c68c319a0113be832da17a777892353a8b5f23Kostya SerebryanyFakeStack *FakeStack::Create(uptr stack_size_log) {
39e1c68c319a0113be832da17a777892353a8b5f23Kostya Serebryany  static uptr kMinStackSizeLog = 16;
40e1c68c319a0113be832da17a777892353a8b5f23Kostya Serebryany  static uptr kMaxStackSizeLog = FIRST_32_SECOND_64(24, 28);
41e1c68c319a0113be832da17a777892353a8b5f23Kostya Serebryany  if (stack_size_log < kMinStackSizeLog)
42e1c68c319a0113be832da17a777892353a8b5f23Kostya Serebryany    stack_size_log = kMinStackSizeLog;
43e1c68c319a0113be832da17a777892353a8b5f23Kostya Serebryany  if (stack_size_log > kMaxStackSizeLog)
44e1c68c319a0113be832da17a777892353a8b5f23Kostya Serebryany    stack_size_log = kMaxStackSizeLog;
452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  uptr size = RequiredSize(stack_size_log);
46e1c68c319a0113be832da17a777892353a8b5f23Kostya Serebryany  FakeStack *res = reinterpret_cast<FakeStack *>(
472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      flags()->uar_noreserve ? MmapNoReserveOrDie(size, "FakeStack")
482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                             : MmapOrDie(size, "FakeStack"));
49e1c68c319a0113be832da17a777892353a8b5f23Kostya Serebryany  res->stack_size_log_ = stack_size_log;
502d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  u8 *p = reinterpret_cast<u8 *>(res);
512d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  VReport(1, "T%d: FakeStack created: %p -- %p stack_size_log: %zd; "
522d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines          "mmapped %zdK, noreserve=%d \n",
532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines          GetCurrentTidOrInvalid(), p,
542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines          p + FakeStack::RequiredSize(stack_size_log), stack_size_log,
552d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines          size >> 10, flags()->uar_noreserve);
56e1c68c319a0113be832da17a777892353a8b5f23Kostya Serebryany  return res;
57e1c68c319a0113be832da17a777892353a8b5f23Kostya Serebryany}
58e1c68c319a0113be832da17a777892353a8b5f23Kostya Serebryany
592d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid FakeStack::Destroy(int tid) {
60e1c68c319a0113be832da17a777892353a8b5f23Kostya Serebryany  PoisonAll(0);
612d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (common_flags()->verbosity >= 2) {
622d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    InternalScopedString str(kNumberOfSizeClasses * 50);
632d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    for (uptr class_id = 0; class_id < kNumberOfSizeClasses; class_id++)
642d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      str.append("%zd: %zd/%zd; ", class_id, hint_position_[class_id],
652d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                 NumberOfFrames(stack_size_log(), class_id));
662d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    Report("T%d: FakeStack destroyed: %s\n", tid, str.data());
672d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  }
682d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  uptr size = RequiredSize(stack_size_log_);
692d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  FlushUnneededASanShadowMemory(reinterpret_cast<uptr>(this), size);
702d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  UnmapOrDie(this, size);
71e1c68c319a0113be832da17a777892353a8b5f23Kostya Serebryany}
72e1c68c319a0113be832da17a777892353a8b5f23Kostya Serebryany
73ac3ae5dc29d3623ada2bcb0db22ee88b0382e3b1Kostya Serebryanyvoid FakeStack::PoisonAll(u8 magic) {
74ac3ae5dc29d3623ada2bcb0db22ee88b0382e3b1Kostya Serebryany  PoisonShadow(reinterpret_cast<uptr>(this), RequiredSize(stack_size_log()),
75ac3ae5dc29d3623ada2bcb0db22ee88b0382e3b1Kostya Serebryany               magic);
762679f1904dc5d5eb2ce82014116764c5f5131a2bKostya Serebryany}
772679f1904dc5d5eb2ce82014116764c5f5131a2bKostya Serebryany
78b1173c27c2791aef27304e68911a11648401064dKostya SerebryanyALWAYS_INLINE USED
79ac3ae5dc29d3623ada2bcb0db22ee88b0382e3b1Kostya SerebryanyFakeFrame *FakeStack::Allocate(uptr stack_size_log, uptr class_id,
80ac3ae5dc29d3623ada2bcb0db22ee88b0382e3b1Kostya Serebryany                               uptr real_stack) {
81ac3ae5dc29d3623ada2bcb0db22ee88b0382e3b1Kostya Serebryany  CHECK_LT(class_id, kNumberOfSizeClasses);
8289de457bd3ec40d38bc7860f88f1d4da473eacc4Kostya Serebryany  if (needs_gc_)
8389de457bd3ec40d38bc7860f88f1d4da473eacc4Kostya Serebryany    GC(real_stack);
84ac3ae5dc29d3623ada2bcb0db22ee88b0382e3b1Kostya Serebryany  uptr &hint_position = hint_position_[class_id];
85ac3ae5dc29d3623ada2bcb0db22ee88b0382e3b1Kostya Serebryany  const int num_iter = NumberOfFrames(stack_size_log, class_id);
86ac3ae5dc29d3623ada2bcb0db22ee88b0382e3b1Kostya Serebryany  u8 *flags = GetFlags(stack_size_log, class_id);
87ac3ae5dc29d3623ada2bcb0db22ee88b0382e3b1Kostya Serebryany  for (int i = 0; i < num_iter; i++) {
88ac3ae5dc29d3623ada2bcb0db22ee88b0382e3b1Kostya Serebryany    uptr pos = ModuloNumberOfFrames(stack_size_log, class_id, hint_position++);
89dff16d41223d2df3762ba64a0a529c5e475de34fKostya Serebryany    // This part is tricky. On one hand, checking and setting flags[pos]
90dff16d41223d2df3762ba64a0a529c5e475de34fKostya Serebryany    // should be atomic to ensure async-signal safety. But on the other hand,
91dff16d41223d2df3762ba64a0a529c5e475de34fKostya Serebryany    // if the signal arrives between checking and setting flags[pos], the
92dff16d41223d2df3762ba64a0a529c5e475de34fKostya Serebryany    // signal handler's fake stack will start from a different hint_position
93dff16d41223d2df3762ba64a0a529c5e475de34fKostya Serebryany    // and so will not touch this particular byte. So, it is safe to do this
94dff16d41223d2df3762ba64a0a529c5e475de34fKostya Serebryany    // with regular non-atimic load and store (at least I was not able to make
95dff16d41223d2df3762ba64a0a529c5e475de34fKostya Serebryany    // this code crash).
96ac3ae5dc29d3623ada2bcb0db22ee88b0382e3b1Kostya Serebryany    if (flags[pos]) continue;
97dff16d41223d2df3762ba64a0a529c5e475de34fKostya Serebryany    flags[pos] = 1;
98dff16d41223d2df3762ba64a0a529c5e475de34fKostya Serebryany    FakeFrame *res = reinterpret_cast<FakeFrame *>(
99dff16d41223d2df3762ba64a0a529c5e475de34fKostya Serebryany        GetFrame(stack_size_log, class_id, pos));
100dff16d41223d2df3762ba64a0a529c5e475de34fKostya Serebryany    res->real_stack = real_stack;
101b388987bf988435ee87dc4848ea8e62ebfa942ebKostya Serebryany    *SavedFlagPtr(reinterpret_cast<uptr>(res), class_id) = &flags[pos];
102dff16d41223d2df3762ba64a0a529c5e475de34fKostya Serebryany    return res;
1032679f1904dc5d5eb2ce82014116764c5f5131a2bKostya Serebryany  }
104e1c68c319a0113be832da17a777892353a8b5f23Kostya Serebryany  return 0; // We are out of fake stack.
1052679f1904dc5d5eb2ce82014116764c5f5131a2bKostya Serebryany}
1062679f1904dc5d5eb2ce82014116764c5f5131a2bKostya Serebryany
1072d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesuptr FakeStack::AddrIsInFakeStack(uptr ptr, uptr *frame_beg, uptr *frame_end) {
108ac3ae5dc29d3623ada2bcb0db22ee88b0382e3b1Kostya Serebryany  uptr stack_size_log = this->stack_size_log();
109ac3ae5dc29d3623ada2bcb0db22ee88b0382e3b1Kostya Serebryany  uptr beg = reinterpret_cast<uptr>(GetFrame(stack_size_log, 0, 0));
110ac3ae5dc29d3623ada2bcb0db22ee88b0382e3b1Kostya Serebryany  uptr end = reinterpret_cast<uptr>(this) + RequiredSize(stack_size_log);
111ac3ae5dc29d3623ada2bcb0db22ee88b0382e3b1Kostya Serebryany  if (ptr < beg || ptr >= end) return 0;
112ac3ae5dc29d3623ada2bcb0db22ee88b0382e3b1Kostya Serebryany  uptr class_id = (ptr - beg) >> stack_size_log;
113ac3ae5dc29d3623ada2bcb0db22ee88b0382e3b1Kostya Serebryany  uptr base = beg + (class_id << stack_size_log);
114ac3ae5dc29d3623ada2bcb0db22ee88b0382e3b1Kostya Serebryany  CHECK_LE(base, ptr);
115ac3ae5dc29d3623ada2bcb0db22ee88b0382e3b1Kostya Serebryany  CHECK_LT(ptr, base + (1UL << stack_size_log));
116ac3ae5dc29d3623ada2bcb0db22ee88b0382e3b1Kostya Serebryany  uptr pos = (ptr - base) >> (kMinStackFrameSizeLog + class_id);
1172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  uptr res = base + pos * BytesInSizeClass(class_id);
1182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  *frame_end = res + BytesInSizeClass(class_id);
1192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  *frame_beg = res + sizeof(FakeFrame);
1202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return res;
1212679f1904dc5d5eb2ce82014116764c5f5131a2bKostya Serebryany}
1222679f1904dc5d5eb2ce82014116764c5f5131a2bKostya Serebryany
12389de457bd3ec40d38bc7860f88f1d4da473eacc4Kostya Serebryanyvoid FakeStack::HandleNoReturn() {
12489de457bd3ec40d38bc7860f88f1d4da473eacc4Kostya Serebryany  needs_gc_ = true;
12589de457bd3ec40d38bc7860f88f1d4da473eacc4Kostya Serebryany}
12689de457bd3ec40d38bc7860f88f1d4da473eacc4Kostya Serebryany
12789de457bd3ec40d38bc7860f88f1d4da473eacc4Kostya Serebryany// When throw, longjmp or some such happens we don't call OnFree() and
12889de457bd3ec40d38bc7860f88f1d4da473eacc4Kostya Serebryany// as the result may leak one or more fake frames, but the good news is that
12989de457bd3ec40d38bc7860f88f1d4da473eacc4Kostya Serebryany// we are notified about all such events by HandleNoReturn().
13089de457bd3ec40d38bc7860f88f1d4da473eacc4Kostya Serebryany// If we recently had such no-return event we need to collect garbage frames.
13189de457bd3ec40d38bc7860f88f1d4da473eacc4Kostya Serebryany// We do it based on their 'real_stack' values -- everything that is lower
13289de457bd3ec40d38bc7860f88f1d4da473eacc4Kostya Serebryany// than the current real_stack is garbage.
13389de457bd3ec40d38bc7860f88f1d4da473eacc4Kostya SerebryanyNOINLINE void FakeStack::GC(uptr real_stack) {
13489de457bd3ec40d38bc7860f88f1d4da473eacc4Kostya Serebryany  uptr collected = 0;
13589de457bd3ec40d38bc7860f88f1d4da473eacc4Kostya Serebryany  for (uptr class_id = 0; class_id < kNumberOfSizeClasses; class_id++) {
13689de457bd3ec40d38bc7860f88f1d4da473eacc4Kostya Serebryany    u8 *flags = GetFlags(stack_size_log(), class_id);
13789de457bd3ec40d38bc7860f88f1d4da473eacc4Kostya Serebryany    for (uptr i = 0, n = NumberOfFrames(stack_size_log(), class_id); i < n;
13889de457bd3ec40d38bc7860f88f1d4da473eacc4Kostya Serebryany         i++) {
13989de457bd3ec40d38bc7860f88f1d4da473eacc4Kostya Serebryany      if (flags[i] == 0) continue;  // not allocated.
14089de457bd3ec40d38bc7860f88f1d4da473eacc4Kostya Serebryany      FakeFrame *ff = reinterpret_cast<FakeFrame *>(
14189de457bd3ec40d38bc7860f88f1d4da473eacc4Kostya Serebryany          GetFrame(stack_size_log(), class_id, i));
14289de457bd3ec40d38bc7860f88f1d4da473eacc4Kostya Serebryany      if (ff->real_stack < real_stack) {
14389de457bd3ec40d38bc7860f88f1d4da473eacc4Kostya Serebryany        flags[i] = 0;
14489de457bd3ec40d38bc7860f88f1d4da473eacc4Kostya Serebryany        collected++;
14589de457bd3ec40d38bc7860f88f1d4da473eacc4Kostya Serebryany      }
14689de457bd3ec40d38bc7860f88f1d4da473eacc4Kostya Serebryany    }
14789de457bd3ec40d38bc7860f88f1d4da473eacc4Kostya Serebryany  }
14889de457bd3ec40d38bc7860f88f1d4da473eacc4Kostya Serebryany  needs_gc_ = false;
14989de457bd3ec40d38bc7860f88f1d4da473eacc4Kostya Serebryany}
15089de457bd3ec40d38bc7860f88f1d4da473eacc4Kostya Serebryany
151c519335c2d6d32acaac32c0595f08a05081567e7Sergey Matveevvoid FakeStack::ForEachFakeFrame(RangeIteratorCallback callback, void *arg) {
152c519335c2d6d32acaac32c0595f08a05081567e7Sergey Matveev  for (uptr class_id = 0; class_id < kNumberOfSizeClasses; class_id++) {
153c519335c2d6d32acaac32c0595f08a05081567e7Sergey Matveev    u8 *flags = GetFlags(stack_size_log(), class_id);
154c519335c2d6d32acaac32c0595f08a05081567e7Sergey Matveev    for (uptr i = 0, n = NumberOfFrames(stack_size_log(), class_id); i < n;
155c519335c2d6d32acaac32c0595f08a05081567e7Sergey Matveev         i++) {
156c519335c2d6d32acaac32c0595f08a05081567e7Sergey Matveev      if (flags[i] == 0) continue;  // not allocated.
157c519335c2d6d32acaac32c0595f08a05081567e7Sergey Matveev      FakeFrame *ff = reinterpret_cast<FakeFrame *>(
158c519335c2d6d32acaac32c0595f08a05081567e7Sergey Matveev          GetFrame(stack_size_log(), class_id, i));
159c519335c2d6d32acaac32c0595f08a05081567e7Sergey Matveev      uptr begin = reinterpret_cast<uptr>(ff);
160c519335c2d6d32acaac32c0595f08a05081567e7Sergey Matveev      callback(begin, begin + FakeStack::BytesInSizeClass(class_id), arg);
161c519335c2d6d32acaac32c0595f08a05081567e7Sergey Matveev    }
162c519335c2d6d32acaac32c0595f08a05081567e7Sergey Matveev  }
163c519335c2d6d32acaac32c0595f08a05081567e7Sergey Matveev}
164c519335c2d6d32acaac32c0595f08a05081567e7Sergey Matveev
165ff64012e04faede5eaecd68db0edd86e8b15853cKostya Serebryany#if SANITIZER_LINUX && !SANITIZER_ANDROID
1669433af375c7813486be91d2ac76f5072ee41818dKostya Serebryanystatic THREADLOCAL FakeStack *fake_stack_tls;
1679433af375c7813486be91d2ac76f5072ee41818dKostya Serebryany
1689433af375c7813486be91d2ac76f5072ee41818dKostya SerebryanyFakeStack *GetTLSFakeStack() {
1699433af375c7813486be91d2ac76f5072ee41818dKostya Serebryany  return fake_stack_tls;
1709433af375c7813486be91d2ac76f5072ee41818dKostya Serebryany}
1719433af375c7813486be91d2ac76f5072ee41818dKostya Serebryanyvoid SetTLSFakeStack(FakeStack *fs) {
1729433af375c7813486be91d2ac76f5072ee41818dKostya Serebryany  fake_stack_tls = fs;
1739433af375c7813486be91d2ac76f5072ee41818dKostya Serebryany}
1749433af375c7813486be91d2ac76f5072ee41818dKostya Serebryany#else
1759433af375c7813486be91d2ac76f5072ee41818dKostya SerebryanyFakeStack *GetTLSFakeStack() { return 0; }
1769433af375c7813486be91d2ac76f5072ee41818dKostya Serebryanyvoid SetTLSFakeStack(FakeStack *fs) { }
177ff64012e04faede5eaecd68db0edd86e8b15853cKostya Serebryany#endif  // SANITIZER_LINUX && !SANITIZER_ANDROID
1789433af375c7813486be91d2ac76f5072ee41818dKostya Serebryany
1796147f02a9116a79b608b9ef547ccca51c70bffe2Kostya Serebryanystatic FakeStack *GetFakeStack() {
18089c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov  AsanThread *t = GetCurrentThread();
1816147f02a9116a79b608b9ef547ccca51c70bffe2Kostya Serebryany  if (!t) return 0;
1826147f02a9116a79b608b9ef547ccca51c70bffe2Kostya Serebryany  return t->fake_stack();
1836147f02a9116a79b608b9ef547ccca51c70bffe2Kostya Serebryany}
1846147f02a9116a79b608b9ef547ccca51c70bffe2Kostya Serebryany
1856147f02a9116a79b608b9ef547ccca51c70bffe2Kostya Serebryanystatic FakeStack *GetFakeStackFast() {
1869433af375c7813486be91d2ac76f5072ee41818dKostya Serebryany  if (FakeStack *fs = GetTLSFakeStack())
1879433af375c7813486be91d2ac76f5072ee41818dKostya Serebryany    return fs;
188230e52f4e91b53f05ce19dbbf11047f4a0113483Kostya Serebryany  if (!__asan_option_detect_stack_use_after_return)
189230e52f4e91b53f05ce19dbbf11047f4a0113483Kostya Serebryany    return 0;
1906147f02a9116a79b608b9ef547ccca51c70bffe2Kostya Serebryany  return GetFakeStack();
1916147f02a9116a79b608b9ef547ccca51c70bffe2Kostya Serebryany}
1926147f02a9116a79b608b9ef547ccca51c70bffe2Kostya Serebryany
1936147f02a9116a79b608b9ef547ccca51c70bffe2Kostya SerebryanyALWAYS_INLINE uptr OnMalloc(uptr class_id, uptr size, uptr real_stack) {
1946147f02a9116a79b608b9ef547ccca51c70bffe2Kostya Serebryany  FakeStack *fs = GetFakeStackFast();
195c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany  if (!fs) return real_stack;
196ac3ae5dc29d3623ada2bcb0db22ee88b0382e3b1Kostya Serebryany  FakeFrame *ff = fs->Allocate(fs->stack_size_log(), class_id, real_stack);
197e1c68c319a0113be832da17a777892353a8b5f23Kostya Serebryany  if (!ff)
198e1c68c319a0113be832da17a777892353a8b5f23Kostya Serebryany    return real_stack;  // Out of fake stack, return the real one.
199ac3ae5dc29d3623ada2bcb0db22ee88b0382e3b1Kostya Serebryany  uptr ptr = reinterpret_cast<uptr>(ff);
2008f7ec32eb34fb051f22e10b228ac056f919c4284Kostya Serebryany  SetShadow(ptr, size, class_id, 0);
2012679f1904dc5d5eb2ce82014116764c5f5131a2bKostya Serebryany  return ptr;
2022679f1904dc5d5eb2ce82014116764c5f5131a2bKostya Serebryany}
2032679f1904dc5d5eb2ce82014116764c5f5131a2bKostya Serebryany
20434e3ed1db94c5ce9784d7ffb8d66a54cf523e09cKostya SerebryanyALWAYS_INLINE void OnFree(uptr ptr, uptr class_id, uptr size, uptr real_stack) {
205ac3ae5dc29d3623ada2bcb0db22ee88b0382e3b1Kostya Serebryany  if (ptr == real_stack)
206ac3ae5dc29d3623ada2bcb0db22ee88b0382e3b1Kostya Serebryany    return;
207b388987bf988435ee87dc4848ea8e62ebfa942ebKostya Serebryany  FakeStack::Deallocate(ptr, class_id);
2088f7ec32eb34fb051f22e10b228ac056f919c4284Kostya Serebryany  SetShadow(ptr, size, class_id, kMagic8);
2092679f1904dc5d5eb2ce82014116764c5f5131a2bKostya Serebryany}
21034e3ed1db94c5ce9784d7ffb8d66a54cf523e09cKostya Serebryany
21134e3ed1db94c5ce9784d7ffb8d66a54cf523e09cKostya Serebryany}  // namespace __asan
21234e3ed1db94c5ce9784d7ffb8d66a54cf523e09cKostya Serebryany
21334e3ed1db94c5ce9784d7ffb8d66a54cf523e09cKostya Serebryany// ---------------------- Interface ---------------- {{{1
2142d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesusing namespace __asan;
21534e3ed1db94c5ce9784d7ffb8d66a54cf523e09cKostya Serebryany#define DEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(class_id)                       \
21634e3ed1db94c5ce9784d7ffb8d66a54cf523e09cKostya Serebryany  extern "C" SANITIZER_INTERFACE_ATTRIBUTE uptr                                \
21734e3ed1db94c5ce9784d7ffb8d66a54cf523e09cKostya Serebryany  __asan_stack_malloc_##class_id(uptr size, uptr real_stack) {                 \
2182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    return OnMalloc(class_id, size, real_stack);                               \
21934e3ed1db94c5ce9784d7ffb8d66a54cf523e09cKostya Serebryany  }                                                                            \
22034e3ed1db94c5ce9784d7ffb8d66a54cf523e09cKostya Serebryany  extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __asan_stack_free_##class_id(  \
22134e3ed1db94c5ce9784d7ffb8d66a54cf523e09cKostya Serebryany      uptr ptr, uptr size, uptr real_stack) {                                  \
2222d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    OnFree(ptr, class_id, size, real_stack);                                   \
22334e3ed1db94c5ce9784d7ffb8d66a54cf523e09cKostya Serebryany  }
22434e3ed1db94c5ce9784d7ffb8d66a54cf523e09cKostya Serebryany
22534e3ed1db94c5ce9784d7ffb8d66a54cf523e09cKostya SerebryanyDEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(0)
22634e3ed1db94c5ce9784d7ffb8d66a54cf523e09cKostya SerebryanyDEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(1)
22734e3ed1db94c5ce9784d7ffb8d66a54cf523e09cKostya SerebryanyDEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(2)
22834e3ed1db94c5ce9784d7ffb8d66a54cf523e09cKostya SerebryanyDEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(3)
22934e3ed1db94c5ce9784d7ffb8d66a54cf523e09cKostya SerebryanyDEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(4)
23034e3ed1db94c5ce9784d7ffb8d66a54cf523e09cKostya SerebryanyDEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(5)
23134e3ed1db94c5ce9784d7ffb8d66a54cf523e09cKostya SerebryanyDEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(6)
23234e3ed1db94c5ce9784d7ffb8d66a54cf523e09cKostya SerebryanyDEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(7)
23334e3ed1db94c5ce9784d7ffb8d66a54cf523e09cKostya SerebryanyDEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(8)
23434e3ed1db94c5ce9784d7ffb8d66a54cf523e09cKostya SerebryanyDEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(9)
23534e3ed1db94c5ce9784d7ffb8d66a54cf523e09cKostya SerebryanyDEFINE_STACK_MALLOC_FREE_WITH_CLASS_ID(10)
2362d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesextern "C" {
2372d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesSANITIZER_INTERFACE_ATTRIBUTE
2382d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid *__asan_get_current_fake_stack() { return GetFakeStackFast(); }
2392d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
2402d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesSANITIZER_INTERFACE_ATTRIBUTE
2412d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid *__asan_addr_is_in_fake_stack(void *fake_stack, void *addr, void **beg,
2422d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines                                   void **end) {
2432d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  FakeStack *fs = reinterpret_cast<FakeStack*>(fake_stack);
2442d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (!fs) return 0;
2452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  uptr frame_beg, frame_end;
2462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  FakeFrame *frame = reinterpret_cast<FakeFrame *>(fs->AddrIsInFakeStack(
2472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      reinterpret_cast<uptr>(addr), &frame_beg, &frame_end));
2482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (!frame) return 0;
2492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (frame->magic != kCurrentStackFrameMagic)
2502d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    return 0;
2512d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (beg) *beg = reinterpret_cast<void*>(frame_beg);
2522d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (end) *end = reinterpret_cast<void*>(frame_end);
2532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return reinterpret_cast<void*>(frame->real_stack);
2542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
2552d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}  // extern "C"
256