tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

stacktrace.h (12869B)


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