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