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 | |
23 | namespace folly { |
24 | namespace exception_tracer { |
25 | |
26 | constexpr size_t kMaxFrames = 500; |
27 | |
28 | struct 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. |
37 | class 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 | |