/src/abseil-cpp/absl/debugging/stacktrace.h
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright 2018 The Abseil Authors. |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | | // you may not use this file except in compliance with the License. |
5 | | // You may obtain a copy of the License at |
6 | | // |
7 | | // https://www.apache.org/licenses/LICENSE-2.0 |
8 | | // |
9 | | // Unless required by applicable law or agreed to in writing, software |
10 | | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | | // See the License for the specific language governing permissions and |
13 | | // limitations under the License. |
14 | | // |
15 | | // ----------------------------------------------------------------------------- |
16 | | // File: stacktrace.h |
17 | | // ----------------------------------------------------------------------------- |
18 | | // |
19 | | // This file contains routines to extract the current stack trace and associated |
20 | | // stack frames. These functions are thread-safe and async-signal-safe. |
21 | | // |
22 | | // Note that stack trace functionality is platform dependent and requires |
23 | | // additional support from the compiler/build system in most cases. (That is, |
24 | | // this functionality generally only works on platforms/builds that have been |
25 | | // specifically configured to support it.) |
26 | | // |
27 | | // Note: stack traces in Abseil that do not utilize a symbolizer will result in |
28 | | // frames consisting of function addresses rather than human-readable function |
29 | | // names. (See symbolize.h for information on symbolizing these values.) |
30 | | |
31 | | #ifndef ABSL_DEBUGGING_STACKTRACE_H_ |
32 | | #define ABSL_DEBUGGING_STACKTRACE_H_ |
33 | | |
34 | | #include <stddef.h> |
35 | | #include <stdint.h> |
36 | | |
37 | | #include "absl/base/attributes.h" |
38 | | #include "absl/base/config.h" |
39 | | |
40 | | namespace absl { |
41 | | ABSL_NAMESPACE_BEGIN |
42 | | |
43 | | namespace internal_stacktrace { |
44 | | |
45 | | // Same as `absl::GetStackFrames`, but with an optional `frames` parameter to |
46 | | // allow callers to receive the raw stack frame addresses. |
47 | | // This is internal for now; use `absl::GetStackFrames()` instead. |
48 | | extern int GetStackFrames(void** result, uintptr_t* frames, int* sizes, |
49 | | int max_depth, int skip_count); |
50 | | |
51 | | // Same as `absl::GetStackFramesWithContext`, but with an optional `frames` |
52 | | // parameter to allow callers to receive a start address for each stack frame. |
53 | | // The address may be zero in cases where it cannot be computed. |
54 | | // |
55 | | // DO NOT use this function without consulting the owners of absl/debuggging. |
56 | | // There is NO GUARANTEE on the precise frame addresses returned on any given |
57 | | // platform. It is only intended to provide sufficient non-overlapping bounds on |
58 | | // the local variables of a stack frame when used in conjunction with the |
59 | | // returned frame sizes. The actual pointers may be ABI-dependent, may vary at |
60 | | // run time, and are subject to breakage without notice. |
61 | | // |
62 | | // Implementation note: |
63 | | // Currently, we *attempt* to return the Canonical Frame Address (CFA) in DWARF |
64 | | // on most platforms. This is the value of the stack pointer just before the |
65 | | // 'call' instruction is executed in the caller. |
66 | | // Not all platforms and toolchains support this exact address, so this should |
67 | | // not be relied on for correctness. |
68 | | extern int GetStackFramesWithContext(void** result, uintptr_t* frames, |
69 | | int* sizes, int max_depth, int skip_count, |
70 | | const void* uc, int* min_dropped_frames); |
71 | | |
72 | | // Same as `absl::DefaultStackUnwinder`, but with an optional `frames` parameter |
73 | | // to allow callers to receive the raw stack frame addresses. |
74 | | // This is internal for now; do not depend on this externally. |
75 | | extern int DefaultStackUnwinder(void** pcs, uintptr_t* frames, int* sizes, |
76 | | int max_depth, int skip_count, const void* uc, |
77 | | int* min_dropped_frames); |
78 | | |
79 | | } // namespace internal_stacktrace |
80 | | |
81 | | // GetStackFrames() |
82 | | // |
83 | | // Records program counter values for up to `max_depth` frames, skipping the |
84 | | // most recent `skip_count` stack frames, stores their corresponding values |
85 | | // and sizes in `results` and `sizes` buffers, and returns the number of frames |
86 | | // stored. (Note that the frame generated for the `absl::GetStackFrames()` |
87 | | // routine itself is also skipped.) |
88 | | // |
89 | | // Example: |
90 | | // |
91 | | // main() { foo(); } |
92 | | // foo() { bar(); } |
93 | | // bar() { |
94 | | // void* result[10]; |
95 | | // int sizes[10]; |
96 | | // int depth = absl::GetStackFrames(result, sizes, 10, 1); |
97 | | // } |
98 | | // |
99 | | // The current stack frame would consist of three function calls: `bar()`, |
100 | | // `foo()`, and then `main()`; however, since the `GetStackFrames()` call sets |
101 | | // `skip_count` to `1`, it will skip the frame for `bar()`, the most recently |
102 | | // invoked function call. It will therefore return 2 and fill `result` with |
103 | | // program counters within the following functions: |
104 | | // |
105 | | // result[0] foo() |
106 | | // result[1] main() |
107 | | // |
108 | | // (Note: in practice, a few more entries after `main()` may be added to account |
109 | | // for startup processes.) |
110 | | // |
111 | | // Corresponding stack frame sizes will also be recorded: |
112 | | // |
113 | | // sizes[0] 16 |
114 | | // sizes[1] 16 |
115 | | // |
116 | | // (Stack frame sizes of `16` above are just for illustration purposes.) |
117 | | // |
118 | | // Stack frame sizes of 0 or less indicate that those frame sizes couldn't |
119 | | // be identified. |
120 | | // |
121 | | // This routine may return fewer stack frame entries than are |
122 | | // available. Also note that `result` and `sizes` must both be non-null. |
123 | | ABSL_ATTRIBUTE_ALWAYS_INLINE inline int GetStackFrames(void** result, |
124 | | int* sizes, |
125 | | int max_depth, |
126 | 0 | int skip_count) { |
127 | 0 | return internal_stacktrace::GetStackFrames(result, nullptr, sizes, max_depth, |
128 | 0 | skip_count); |
129 | 0 | } |
130 | | |
131 | | // GetStackFramesWithContext() |
132 | | // |
133 | | // Records program counter values obtained from a signal handler. Records |
134 | | // program counter values for up to `max_depth` frames, skipping the most recent |
135 | | // `skip_count` stack frames, stores their corresponding values and sizes in |
136 | | // `results` and `sizes` buffers, and returns the number of frames stored. (Note |
137 | | // that the frame generated for the `absl::GetStackFramesWithContext()` routine |
138 | | // itself is also skipped.) |
139 | | // |
140 | | // The `uc` parameter, if non-null, should be a pointer to a `ucontext_t` value |
141 | | // passed to a signal handler registered via the `sa_sigaction` field of a |
142 | | // `sigaction` struct. (See |
143 | | // http://man7.org/linux/man-pages/man2/sigaction.2.html.) The `uc` value may |
144 | | // help a stack unwinder to provide a better stack trace under certain |
145 | | // conditions. `uc` may safely be null. |
146 | | // |
147 | | // The `min_dropped_frames` output parameter, if non-null, points to the |
148 | | // location to note any dropped stack frames, if any, due to buffer limitations |
149 | | // or other reasons. (This value will be set to `0` if no frames were dropped.) |
150 | | // The number of total stack frames is guaranteed to be >= skip_count + |
151 | | // max_depth + *min_dropped_frames. |
152 | | ABSL_ATTRIBUTE_ALWAYS_INLINE inline int GetStackFramesWithContext( |
153 | | void** result, int* sizes, int max_depth, int skip_count, const void* uc, |
154 | 0 | int* min_dropped_frames) { |
155 | 0 | return internal_stacktrace::GetStackFramesWithContext( |
156 | 0 | result, nullptr, sizes, max_depth, skip_count, uc, min_dropped_frames); |
157 | 0 | } |
158 | | |
159 | | // GetStackTrace() |
160 | | // |
161 | | // Records program counter values for up to `max_depth` frames, skipping the |
162 | | // most recent `skip_count` stack frames, stores their corresponding values |
163 | | // in `results`, and returns the number of frames |
164 | | // stored. Note that this function is similar to `absl::GetStackFrames()` |
165 | | // except that it returns the stack trace only, and not stack frame sizes. |
166 | | // |
167 | | // Example: |
168 | | // |
169 | | // main() { foo(); } |
170 | | // foo() { bar(); } |
171 | | // bar() { |
172 | | // void* result[10]; |
173 | | // int depth = absl::GetStackTrace(result, 10, 1); |
174 | | // } |
175 | | // |
176 | | // This produces: |
177 | | // |
178 | | // result[0] foo |
179 | | // result[1] main |
180 | | // .... ... |
181 | | // |
182 | | // `result` must not be null. |
183 | | extern int GetStackTrace(void** result, int max_depth, int skip_count); |
184 | | |
185 | | // GetStackTraceWithContext() |
186 | | // |
187 | | // Records program counter values obtained from a signal handler. Records |
188 | | // program counter values for up to `max_depth` frames, skipping the most recent |
189 | | // `skip_count` stack frames, stores their corresponding values in `results`, |
190 | | // and returns the number of frames stored. (Note that the frame generated for |
191 | | // the `absl::GetStackFramesWithContext()` routine itself is also skipped.) |
192 | | // |
193 | | // The `uc` parameter, if non-null, should be a pointer to a `ucontext_t` value |
194 | | // passed to a signal handler registered via the `sa_sigaction` field of a |
195 | | // `sigaction` struct. (See |
196 | | // http://man7.org/linux/man-pages/man2/sigaction.2.html.) The `uc` value may |
197 | | // help a stack unwinder to provide a better stack trace under certain |
198 | | // conditions. `uc` may safely be null. |
199 | | // |
200 | | // The `min_dropped_frames` output parameter, if non-null, points to the |
201 | | // location to note any dropped stack frames, if any, due to buffer limitations |
202 | | // or other reasons. (This value will be set to `0` if no frames were dropped.) |
203 | | // The number of total stack frames is guaranteed to be >= skip_count + |
204 | | // max_depth + *min_dropped_frames. |
205 | | extern int GetStackTraceWithContext(void** result, int max_depth, |
206 | | int skip_count, const void* uc, |
207 | | int* min_dropped_frames); |
208 | | |
209 | | // SetStackUnwinder() |
210 | | // |
211 | | // Provides a custom function for unwinding stack frames that will be used in |
212 | | // place of the default stack unwinder when invoking the static |
213 | | // GetStack{Frames,Trace}{,WithContext}() functions above. |
214 | | // |
215 | | // The arguments passed to the unwinder function will match the |
216 | | // arguments passed to `absl::GetStackFramesWithContext()` except that sizes |
217 | | // will be non-null iff the caller is interested in frame sizes. |
218 | | // |
219 | | // If unwinder is set to null, we revert to the default stack-tracing behavior. |
220 | | // |
221 | | // ***************************************************************************** |
222 | | // WARNING |
223 | | // ***************************************************************************** |
224 | | // |
225 | | // absl::SetStackUnwinder is not suitable for general purpose use. It is |
226 | | // provided for custom runtimes. |
227 | | // Some things to watch out for when calling `absl::SetStackUnwinder()`: |
228 | | // |
229 | | // (a) The unwinder may be called from within signal handlers and |
230 | | // therefore must be async-signal-safe. |
231 | | // |
232 | | // (b) Even after a custom stack unwinder has been unregistered, other |
233 | | // threads may still be in the process of using that unwinder. |
234 | | // Therefore do not clean up any state that may be needed by an old |
235 | | // unwinder. |
236 | | // ***************************************************************************** |
237 | | extern void SetStackUnwinder(int (*unwinder)(void** pcs, int* sizes, |
238 | | int max_depth, int skip_count, |
239 | | const void* uc, |
240 | | int* min_dropped_frames)); |
241 | | |
242 | | // DefaultStackUnwinder() |
243 | | // |
244 | | // Records program counter values of up to `max_depth` frames, skipping the most |
245 | | // recent `skip_count` stack frames, and stores their corresponding values in |
246 | | // `pcs`. (Note that the frame generated for this call itself is also skipped.) |
247 | | // This function acts as a generic stack-unwinder; prefer usage of the more |
248 | | // specific `GetStack{Trace,Frames}{,WithContext}()` functions above. |
249 | | // |
250 | | // If you have set your own stack unwinder (with the `SetStackUnwinder()` |
251 | | // function above, you can still get the default stack unwinder by calling |
252 | | // `DefaultStackUnwinder()`, which will ignore any previously set stack unwinder |
253 | | // and use the default one instead. |
254 | | // |
255 | | // Because this function is generic, only `pcs` is guaranteed to be non-null |
256 | | // upon return. It is legal for `sizes`, `uc`, and `min_dropped_frames` to all |
257 | | // be null when called. |
258 | | // |
259 | | // The semantics are the same as the corresponding `GetStack*()` function in the |
260 | | // case where `absl::SetStackUnwinder()` was never called. Equivalents are: |
261 | | // |
262 | | // null sizes | non-nullptr sizes |
263 | | // |==========================================================| |
264 | | // null uc | GetStackTrace() | GetStackFrames() | |
265 | | // non-null uc | GetStackTraceWithContext() | GetStackFramesWithContext() | |
266 | | // |==========================================================| |
267 | | extern int DefaultStackUnwinder(void** pcs, int* sizes, int max_depth, |
268 | | int skip_count, const void* uc, |
269 | | int* min_dropped_frames); |
270 | | |
271 | | namespace debugging_internal { |
272 | | // Returns true for platforms which are expected to have functioning stack trace |
273 | | // implementations. Intended to be used for tests which want to exclude |
274 | | // verification of logic known to be broken because stack traces are not |
275 | | // working. |
276 | | extern bool StackTraceWorksForTest(); |
277 | | } // namespace debugging_internal |
278 | | |
279 | | namespace internal_stacktrace { |
280 | | extern bool ShouldFixUpStack(); |
281 | | |
282 | | // Fixes up the stack trace of the current thread, in the first `depth` frames |
283 | | // of each buffer. The buffers need to be larger than `depth`, to accommodate |
284 | | // any newly inserted elements. `depth` is updated to reflect the new number of |
285 | | // elements valid across all the buffers. (It is therefore recommended that all |
286 | | // buffer sizes be equal.) |
287 | | // |
288 | | // The `frames` and `sizes` parameters denote the bounds of the stack frame |
289 | | // corresponding to each instruction pointer in the `pcs`. |
290 | | // Any elements inside these buffers may be zero or null, in which case that |
291 | | // information is assumed to be absent/unavailable. |
292 | | extern void FixUpStack(void** pcs, uintptr_t* frames, int* sizes, |
293 | | size_t capacity, size_t& depth); |
294 | | } // namespace internal_stacktrace |
295 | | |
296 | | ABSL_NAMESPACE_END |
297 | | } // namespace absl |
298 | | |
299 | | #endif // ABSL_DEBUGGING_STACKTRACE_H_ |