00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #include "absl/debugging/stacktrace.h"
00038
00039 #include <atomic>
00040
00041 #include "absl/base/attributes.h"
00042 #include "absl/base/port.h"
00043 #include "absl/debugging/internal/stacktrace_config.h"
00044
00045 #if defined(ABSL_STACKTRACE_INL_HEADER)
00046 #include ABSL_STACKTRACE_INL_HEADER
00047 #else
00048 # error Cannot calculate stack trace: will need to write for your environment
00049
00050 # include "absl/debugging/internal/stacktrace_aarch64-inl.inc"
00051 # include "absl/debugging/internal/stacktrace_arm-inl.inc"
00052 # include "absl/debugging/internal/stacktrace_generic-inl.inc"
00053 # include "absl/debugging/internal/stacktrace_powerpc-inl.inc"
00054 # include "absl/debugging/internal/stacktrace_unimplemented-inl.inc"
00055 # include "absl/debugging/internal/stacktrace_win32-inl.inc"
00056 # include "absl/debugging/internal/stacktrace_x86-inl.inc"
00057 #endif
00058
00059 namespace absl {
00060 namespace {
00061
00062 typedef int (*Unwinder)(void**, int*, int, int, const void*, int*);
00063 std::atomic<Unwinder> custom;
00064
00065 template <bool IS_STACK_FRAMES, bool IS_WITH_CONTEXT>
00066 ABSL_ATTRIBUTE_ALWAYS_INLINE inline int Unwind(void** result, int* sizes,
00067 int max_depth, int skip_count,
00068 const void* uc,
00069 int* min_dropped_frames) {
00070 Unwinder f = &UnwindImpl<IS_STACK_FRAMES, IS_WITH_CONTEXT>;
00071 Unwinder g = custom.load(std::memory_order_acquire);
00072 if (g != nullptr) f = g;
00073
00074
00075 int size = (*f)(result, sizes, max_depth, skip_count + 1, uc,
00076 min_dropped_frames);
00077
00078 ABSL_BLOCK_TAIL_CALL_OPTIMIZATION();
00079 return size;
00080 }
00081
00082 }
00083
00084 ABSL_ATTRIBUTE_NOINLINE ABSL_ATTRIBUTE_NO_TAIL_CALL int GetStackFrames(
00085 void** result, int* sizes, int max_depth, int skip_count) {
00086 return Unwind<true, false>(result, sizes, max_depth, skip_count, nullptr,
00087 nullptr);
00088 }
00089
00090 ABSL_ATTRIBUTE_NOINLINE ABSL_ATTRIBUTE_NO_TAIL_CALL int
00091 GetStackFramesWithContext(void** result, int* sizes, int max_depth,
00092 int skip_count, const void* uc,
00093 int* min_dropped_frames) {
00094 return Unwind<true, true>(result, sizes, max_depth, skip_count, uc,
00095 min_dropped_frames);
00096 }
00097
00098 ABSL_ATTRIBUTE_NOINLINE ABSL_ATTRIBUTE_NO_TAIL_CALL int GetStackTrace(
00099 void** result, int max_depth, int skip_count) {
00100 return Unwind<false, false>(result, nullptr, max_depth, skip_count, nullptr,
00101 nullptr);
00102 }
00103
00104 ABSL_ATTRIBUTE_NOINLINE ABSL_ATTRIBUTE_NO_TAIL_CALL int
00105 GetStackTraceWithContext(void** result, int max_depth, int skip_count,
00106 const void* uc, int* min_dropped_frames) {
00107 return Unwind<false, true>(result, nullptr, max_depth, skip_count, uc,
00108 min_dropped_frames);
00109 }
00110
00111 void SetStackUnwinder(Unwinder w) {
00112 custom.store(w, std::memory_order_release);
00113 }
00114
00115 int DefaultStackUnwinder(void** pcs, int* sizes, int depth, int skip,
00116 const void* uc, int* min_dropped_frames) {
00117 skip++;
00118 Unwinder f = nullptr;
00119 if (sizes == nullptr) {
00120 if (uc == nullptr) {
00121 f = &UnwindImpl<false, false>;
00122 } else {
00123 f = &UnwindImpl<false, true>;
00124 }
00125 } else {
00126 if (uc == nullptr) {
00127 f = &UnwindImpl<true, false>;
00128 } else {
00129 f = &UnwindImpl<true, true>;
00130 }
00131 }
00132 volatile int x = 0;
00133 int n = (*f)(pcs, sizes, depth, skip, uc, min_dropped_frames);
00134 x = 1; (void) x;
00135 return n;
00136 }
00137
00138 }