2014-10-24 Richard Biener <rguenther@suse.de>
[official-gcc.git] / libsanitizer / tsan / tsan_stack_trace.cc
blob45bd2517837261384aa04228f929f126d44cc1c5
1 //===-- tsan_stack_trace.cc -----------------------------------------------===//
2 //
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
5 //
6 //===----------------------------------------------------------------------===//
7 //
8 // This file is a part of ThreadSanitizer (TSan), a race detector.
9 //
10 //===----------------------------------------------------------------------===//
11 //#include "sanitizer_common/sanitizer_placement_new.h"
12 #include "tsan_stack_trace.h"
13 #include "tsan_rtl.h"
14 #include "tsan_mman.h"
16 namespace __tsan {
18 StackTrace::StackTrace()
19 : n_()
20 , s_()
21 , c_() {
24 StackTrace::StackTrace(uptr *buf, uptr cnt)
25 : n_()
26 , s_(buf)
27 , c_(cnt) {
28 CHECK_NE(buf, 0);
29 CHECK_NE(cnt, 0);
32 StackTrace::~StackTrace() {
33 Reset();
36 void StackTrace::Reset() {
37 if (s_ && !c_) {
38 CHECK_NE(n_, 0);
39 internal_free(s_);
40 s_ = 0;
42 n_ = 0;
45 void StackTrace::Init(const uptr *pcs, uptr cnt) {
46 Reset();
47 if (cnt == 0)
48 return;
49 if (c_) {
50 CHECK_NE(s_, 0);
51 CHECK_LE(cnt, c_);
52 } else {
53 s_ = (uptr*)internal_alloc(MBlockStackTrace, cnt * sizeof(s_[0]));
55 n_ = cnt;
56 internal_memcpy(s_, pcs, cnt * sizeof(s_[0]));
59 void StackTrace::ObtainCurrent(ThreadState *thr, uptr toppc) {
60 Reset();
61 n_ = thr->shadow_stack_pos - thr->shadow_stack;
62 if (n_ + !!toppc == 0)
63 return;
64 uptr start = 0;
65 if (c_) {
66 CHECK_NE(s_, 0);
67 if (n_ + !!toppc > c_) {
68 start = n_ - c_ + !!toppc;
69 n_ = c_ - !!toppc;
71 } else {
72 // Cap potentially huge stacks.
73 if (n_ + !!toppc > kTraceStackSize) {
74 start = n_ - kTraceStackSize + !!toppc;
75 n_ = kTraceStackSize - !!toppc;
77 s_ = (uptr*)internal_alloc(MBlockStackTrace,
78 (n_ + !!toppc) * sizeof(s_[0]));
80 for (uptr i = 0; i < n_; i++)
81 s_[i] = thr->shadow_stack[start + i];
82 if (toppc) {
83 s_[n_] = toppc;
84 n_++;
88 void StackTrace::CopyFrom(const StackTrace& other) {
89 Reset();
90 Init(other.Begin(), other.Size());
93 bool StackTrace::IsEmpty() const {
94 return n_ == 0;
97 uptr StackTrace::Size() const {
98 return n_;
101 uptr StackTrace::Get(uptr i) const {
102 CHECK_LT(i, n_);
103 return s_[i];
106 const uptr *StackTrace::Begin() const {
107 return s_;
110 } // namespace __tsan