1/*
2 * Copyright 2012-present Facebook, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#pragma once
18
19#include <cassert>
20#include <cstddef>
21#include <cstdint>
22
23namespace folly {
24namespace exception_tracer {
25
26constexpr size_t kMaxFrames = 500;
27
28struct StackTrace {
29 StackTrace() : frameCount(0) {}
30
31 size_t frameCount;
32 uintptr_t addresses[kMaxFrames];
33};
34
35// note: no constructor so this can be __thread.
36// A StackTraceStack MUST be placed in zero-initialized memory.
37class StackTraceStack {
38 class Node;
39
40 public:
41 /**
42 * Push the current stack trace onto the stack.
43 * Returns false on failure (not enough memory, getting stack trace failed),
44 * true on success.
45 */
46 bool pushCurrent();
47
48 /**
49 * Pop the top stack trace from the stack.
50 * Returns true on success, false on failure (stack was empty).
51 */
52 bool pop();
53
54 /**
55 * Move the top stack trace from other onto this.
56 * Returns true on success, false on failure (other was empty).
57 */
58 bool moveTopFrom(StackTraceStack& other);
59
60 /**
61 * Clear the stack.
62 */
63
64 void clear();
65
66 /**
67 * Is the stack empty?
68 */
69 bool empty() const {
70 return !top_;
71 }
72
73 /**
74 * Return the top stack trace, or nullptr if the stack is empty.
75 */
76 StackTrace* top();
77
78 /**
79 * Return the stack trace following p, or nullptr if p is the bottom of
80 * the stack.
81 */
82 StackTrace* next(StackTrace* p);
83
84 private:
85 // In debug mode, we assert that we're in zero-initialized memory by
86 // checking that the two guards around top_ are zero.
87 void checkGuard() const {
88#ifndef NDEBUG
89 assert(guard1_ == 0 && guard2_ == 0);
90#endif
91 }
92
93#ifndef NDEBUG
94 uintptr_t guard1_;
95#endif
96 Node* top_;
97#ifndef NDEBUG
98 uintptr_t guard2_;
99#endif
100};
101} // namespace exception_tracer
102} // namespace folly
103