1 //===-- tsan_stack_trace.cc -----------------------------------------------===//
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 ThreadSanitizer (TSan), a race detector.
11 //
12 //===----------------------------------------------------------------------===//
13 //#include "sanitizer_common/sanitizer_placement_new.h"
14 #include "tsan_stack_trace.h"
15 #include "tsan_rtl.h"
16 #include "tsan_mman.h"
17
18 namespace __tsan {
19
StackTrace()20 StackTrace::StackTrace()
21 : n_()
22 , s_()
23 , c_() {
24 }
25
StackTrace(uptr * buf,uptr cnt)26 StackTrace::StackTrace(uptr *buf, uptr cnt)
27 : n_()
28 , s_(buf)
29 , c_(cnt) {
30 CHECK_NE(buf, 0);
31 CHECK_NE(cnt, 0);
32 }
33
~StackTrace()34 StackTrace::~StackTrace() {
35 Reset();
36 }
37
Reset()38 void StackTrace::Reset() {
39 if (s_ && !c_) {
40 CHECK_NE(n_, 0);
41 internal_free(s_);
42 s_ = 0;
43 }
44 n_ = 0;
45 }
46
Init(const uptr * pcs,uptr cnt)47 void StackTrace::Init(const uptr *pcs, uptr cnt) {
48 Reset();
49 if (cnt == 0)
50 return;
51 if (c_) {
52 CHECK_NE(s_, 0);
53 CHECK_LE(cnt, c_);
54 } else {
55 s_ = (uptr*)internal_alloc(MBlockStackTrace, cnt * sizeof(s_[0]));
56 }
57 n_ = cnt;
58 internal_memcpy(s_, pcs, cnt * sizeof(s_[0]));
59 }
60
ObtainCurrent(ThreadState * thr,uptr toppc)61 void StackTrace::ObtainCurrent(ThreadState *thr, uptr toppc) {
62 Reset();
63 n_ = thr->shadow_stack_pos - thr->shadow_stack;
64 if (n_ + !!toppc == 0)
65 return;
66 uptr start = 0;
67 if (c_) {
68 CHECK_NE(s_, 0);
69 if (n_ + !!toppc > c_) {
70 start = n_ - c_ + !!toppc;
71 n_ = c_ - !!toppc;
72 }
73 } else {
74 // Cap potentially huge stacks.
75 if (n_ + !!toppc > kTraceStackSize) {
76 start = n_ - kTraceStackSize + !!toppc;
77 n_ = kTraceStackSize - !!toppc;
78 }
79 s_ = (uptr*)internal_alloc(MBlockStackTrace,
80 (n_ + !!toppc) * sizeof(s_[0]));
81 }
82 for (uptr i = 0; i < n_; i++)
83 s_[i] = thr->shadow_stack[start + i];
84 if (toppc) {
85 s_[n_] = toppc;
86 n_++;
87 }
88 }
89
CopyFrom(const StackTrace & other)90 void StackTrace::CopyFrom(const StackTrace& other) {
91 Reset();
92 Init(other.Begin(), other.Size());
93 }
94
IsEmpty() const95 bool StackTrace::IsEmpty() const {
96 return n_ == 0;
97 }
98
Size() const99 uptr StackTrace::Size() const {
100 return n_;
101 }
102
Get(uptr i) const103 uptr StackTrace::Get(uptr i) const {
104 CHECK_LT(i, n_);
105 return s_[i];
106 }
107
Begin() const108 const uptr *StackTrace::Begin() const {
109 return s_;
110 }
111
112 } // namespace __tsan
113