stacktrace.h
Go to the documentation of this file.
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 namespace absl {
35 
36 // GetStackFrames()
37 //
38 // Records program counter values for up to `max_depth` frames, skipping the
39 // most recent `skip_count` stack frames, and stores their corresponding values
40 // and sizes in `results` and `sizes` buffers. (Note that the frame generated
41 // for the `absl::GetStackFrames()` routine itself is also skipped.)
42 // routine itself.
43 //
44 // Example:
45 //
46 // main() { foo(); }
47 // foo() { bar(); }
48 // bar() {
49 // void* result[10];
50 // int sizes[10];
51 // int depth = absl::GetStackFrames(result, sizes, 10, 1);
52 // }
53 //
54 // The current stack frame would consist of three function calls: `bar()`,
55 // `foo()`, and then `main()`; however, since the `GetStackFrames()` call sets
56 // `skip_count` to `1`, it will skip the frame for `bar()`, the most recently
57 // invoked function call. It will therefore return two program counters and will
58 // produce values that map to the following function calls:
59 //
60 // result[0] foo()
61 // result[1] main()
62 //
63 // (Note: in practice, a few more entries after `main()` may be added to account
64 // for startup processes.)
65 //
66 // Corresponding stack frame sizes will also be recorded:
67 //
68 // sizes[0] 16
69 // sizes[1] 16
70 //
71 // (Stack frame sizes of `16` above are just for illustration purposes.)
72 //
73 // Stack frame sizes of 0 or less indicate that those frame sizes couldn't
74 // be identified.
75 //
76 // This routine may return fewer stack frame entries than are
77 // available. Also note that `result` and `sizes` must both be non-null.
78 extern int GetStackFrames(void** result, int* sizes, int max_depth,
79  int skip_count);
80 
81 // GetStackFramesWithContext()
82 //
83 // Records program counter values obtained from a signal handler. Records
84 // program counter values for up to `max_depth` frames, skipping the most recent
85 // `skip_count` stack frames, and stores their corresponding values and sizes in
86 // `results` and `sizes` buffers. (Note that the frame generated for the
87 // `absl::GetStackFramesWithContext()` routine itself is also skipped.)
88 //
89 // The `uc` parameter, if non-null, should be a pointer to a `ucontext_t` value
90 // passed to a signal handler registered via the `sa_sigaction` field of a
91 // `sigaction` struct. (See
92 // http://man7.org/linux/man-pages/man2/sigaction.2.html.) The `uc` value may
93 // help a stack unwinder to provide a better stack trace under certain
94 // conditions. `uc` may safely be null.
95 //
96 // The `min_dropped_frames` output parameter, if non-null, points to the
97 // location to note any dropped stack frames, if any, due to buffer limitations
98 // or other reasons. (This value will be set to `0` if no frames were dropped.)
99 // The number of total stack frames is guaranteed to be >= skip_count +
100 // max_depth + *min_dropped_frames.
101 extern int GetStackFramesWithContext(void** result, int* sizes, int max_depth,
102  int skip_count, const void* uc,
103  int* min_dropped_frames);
104 
105 // GetStackTrace()
106 //
107 // Records program counter values for up to `max_depth` frames, skipping the
108 // most recent `skip_count` stack frames, and stores their corresponding values
109 // in `results`. Note that this function is similar to `absl::GetStackFrames()`
110 // except that it returns the stack trace only, and not stack frame sizes.
111 //
112 // Example:
113 //
114 // main() { foo(); }
115 // foo() { bar(); }
116 // bar() {
117 // void* result[10];
118 // int depth = absl::GetStackTrace(result, 10, 1);
119 // }
120 //
121 // This produces:
122 //
123 // result[0] foo
124 // result[1] main
125 // .... ...
126 //
127 // `result` must not be null.
128 extern int GetStackTrace(void** result, int max_depth, int skip_count);
129 
130 // GetStackTraceWithContext()
131 //
132 // Records program counter values obtained from a signal handler. Records
133 // program counter values for up to `max_depth` frames, skipping the most recent
134 // `skip_count` stack frames, and stores their corresponding values in
135 // `results`. (Note that the frame generated for the
136 // `absl::GetStackFramesWithContext()` routine itself is also skipped.)
137 //
138 // The `uc` parameter, if non-null, should be a pointer to a `ucontext_t` value
139 // passed to a signal handler registered via the `sa_sigaction` field of a
140 // `sigaction` struct. (See
141 // http://man7.org/linux/man-pages/man2/sigaction.2.html.) The `uc` value may
142 // help a stack unwinder to provide a better stack trace under certain
143 // conditions. `uc` may safely be null.
144 //
145 // The `min_dropped_frames` output parameter, if non-null, points to the
146 // location to note any dropped stack frames, if any, due to buffer limitations
147 // or other reasons. (This value will be set to `0` if no frames were dropped.)
148 // The number of total stack frames is guaranteed to be >= skip_count +
149 // max_depth + *min_dropped_frames.
150 extern int GetStackTraceWithContext(void** result, int max_depth,
151  int skip_count, const void* uc,
152  int* min_dropped_frames);
153 
154 // SetStackUnwinder()
155 //
156 // Provides a custom function for unwinding stack frames that will be used in
157 // place of the default stack unwinder when invoking the static
158 // GetStack{Frames,Trace}{,WithContext}() functions above.
159 //
160 // The arguments passed to the unwinder function will match the
161 // arguments passed to `absl::GetStackFramesWithContext()` except that sizes
162 // will be non-null iff the caller is interested in frame sizes.
163 //
164 // If unwinder is set to null, we revert to the default stack-tracing behavior.
165 //
166 // *****************************************************************************
167 // WARNING
168 // *****************************************************************************
169 //
170 // absl::SetStackUnwinder is not suitable for general purpose use. It is
171 // provided for custom runtimes.
172 // Some things to watch out for when calling `absl::SetStackUnwinder()`:
173 //
174 // (a) The unwinder may be called from within signal handlers and
175 // therefore must be async-signal-safe.
176 //
177 // (b) Even after a custom stack unwinder has been unregistered, other
178 // threads may still be in the process of using that unwinder.
179 // Therefore do not clean up any state that may be needed by an old
180 // unwinder.
181 // *****************************************************************************
182 extern void SetStackUnwinder(int (*unwinder)(void** pcs, int* sizes,
183  int max_depth, int skip_count,
184  const void* uc,
185  int* min_dropped_frames));
186 
187 // DefaultStackUnwinder()
188 //
189 // Records program counter values of up to `max_depth` frames, skipping the most
190 // recent `skip_count` stack frames, and stores their corresponding values in
191 // `pcs`. (Note that the frame generated for this call itself is also skipped.)
192 // This function acts as a generic stack-unwinder; prefer usage of the more
193 // specific `GetStack{Trace,Frames}{,WithContext}()` functions above.
194 //
195 // If you have set your own stack unwinder (with the `SetStackUnwinder()`
196 // function above, you can still get the default stack unwinder by calling
197 // `DefaultStackUnwinder()`, which will ignore any previously set stack unwinder
198 // and use the default one instead.
199 //
200 // Because this function is generic, only `pcs` is guaranteed to be non-null
201 // upon return. It is legal for `sizes`, `uc`, and `min_dropped_frames` to all
202 // be null when called.
203 //
204 // The semantics are the same as the corresponding `GetStack*()` function in the
205 // case where `absl::SetStackUnwinder()` was never called. Equivalents are:
206 //
207 // null sizes | non-nullptr sizes
208 // |==========================================================|
209 // null uc | GetStackTrace() | GetStackFrames() |
210 // non-null uc | GetStackTraceWithContext() | GetStackFramesWithContext() |
211 // |==========================================================|
212 extern int DefaultStackUnwinder(void** pcs, int* sizes, int max_depth,
213  int skip_count, const void* uc,
214  int* min_dropped_frames);
215 
216 namespace debugging_internal {
217 // Returns true for platforms which are expected to have functioning stack trace
218 // implementations. Intended to be used for tests which want to exclude
219 // verification of logic known to be broken because stack traces are not
220 // working.
221 extern bool StackTraceWorksForTest();
222 } // namespace debugging_internal
223 } // namespace absl
224 
225 #endif // ABSL_DEBUGGING_STACKTRACE_H_
ABSL_ATTRIBUTE_NOINLINE ABSL_ATTRIBUTE_NO_TAIL_CALL int GetStackTraceWithContext(void **result, int max_depth, int skip_count, const void *uc, int *min_dropped_frames)
Definition: stacktrace.cc:105
void SetStackUnwinder(Unwinder w)
Definition: stacktrace.cc:111
Definition: algorithm.h:29
int DefaultStackUnwinder(void **pcs, int *sizes, int depth, int skip, const void *uc, int *min_dropped_frames)
Definition: stacktrace.cc:115
ABSL_ATTRIBUTE_NOINLINE ABSL_ATTRIBUTE_NO_TAIL_CALL int GetStackFramesWithContext(void **result, int *sizes, int max_depth, int skip_count, const void *uc, int *min_dropped_frames)
Definition: stacktrace.cc:91
ABSL_ATTRIBUTE_NOINLINE ABSL_ATTRIBUTE_NO_TAIL_CALL int GetStackFrames(void **result, int *sizes, int max_depth, int skip_count)
Definition: stacktrace.cc:84
ABSL_ATTRIBUTE_NOINLINE ABSL_ATTRIBUTE_NO_TAIL_CALL int GetStackTrace(void **result, int max_depth, int skip_count)
Definition: stacktrace.cc:98


abseil_cpp
Author(s):
autogenerated on Mon Feb 28 2022 21:31:20