2121# define ABSL_DEBUGGING_INTERNAL_STACKTRACE_GENERIC_INL_H_
2222
2323# include <execinfo.h>
24+
2425# include <atomic>
26+ # include <cstdint>
2527# include <cstring>
2628
27- # include "absl/debugging/stacktrace.h"
2829# include "absl/base/attributes.h"
30+ # include "absl/debugging/stacktrace.h"
31+
32+ // When the macro __ANDROID_UNAVAILABLE_SYMBOLS_ARE_WEAK__ is defined, Android
33+ // NDK supports a mode where all symbols added later than the target API level
34+ // are weak. In this mode, __builtin_available can be used to check the actual
35+ // API level available at runtime. There is also a compiler warning,
36+ // -Wunguarded-availability, that detects unchecked uses of APIs above the level
37+ // specified by __ANDROID_API__ that are not guarded by __builtin_available.
38+ // Details: https://developer.android.com/ndk/guides/using-newer-apis
39+ //
40+ // We take advantage of this mode to weakly link to backtrace() even when the
41+ // target API level is below 33, which is the first version of Android that
42+ // provides backtrace() in its libc.
43+ //
44+ // Unfortunately, -Wunguarded-availability does not do any control flow analysis
45+ // and will trigger if we do anything other than putting all calls to the target
46+ // function in an if() statement that calls the builtin. We can't return early
47+ // or even negate the condition.
48+ # if defined(__ANDROID__) && defined(__ANDROID_UNAVAILABLE_SYMBOLS_ARE_WEAK__)
49+ // In weak symbol mode, check the compiler builtin.
50+ # define ABSL_INTERNAL_BACKTRACE_AVAILABLE() __builtin_available(android 33, *)
51+ # else
52+ // Otherwise, assume that backtrace() is available, because otherwise this file
53+ // wouldn't be included.
54+ # define ABSL_INTERNAL_BACKTRACE_AVAILABLE() true
55+ # endif
2956
3057// Sometimes, we can try to get a stack trace from within a stack
3158// trace, because we don't block signals inside this code (which would be too
@@ -46,12 +73,14 @@ static std::atomic<bool> disable_stacktraces(true); // Disabled until healthy.
4673// Waiting until static initializers run seems to be late enough.
4774// This file is included into stacktrace.cc so this will only run once.
4875ABSL_ATTRIBUTE_UNUSED static int stacktraces_enabler = []() {
49- void* unused_stack[1 ];
50- // Force the first backtrace to happen early to get the one-time shared lib
51- // loading (allocation) out of the way. After the first call it is much safer
52- // to use backtrace from a signal handler if we crash somewhere later.
53- backtrace (unused_stack, 1 );
54- disable_stacktraces.store (false , std ::memory_order_relaxed);
76+ if (ABSL_INTERNAL_BACKTRACE_AVAILABLE ()) {
77+ void* unused_stack[1 ];
78+ // Force the first backtrace to happen early to get the one-time shared lib
79+ // loading (allocation) out of the way. After the first call it is much
80+ // safer to use backtrace from a signal handler if we crash somewhere later.
81+ backtrace (unused_stack, 1 );
82+ disable_stacktraces.store (false , std ::memory_order_relaxed);
83+ }
5584 return 0 ;
5685}();
5786
@@ -62,43 +91,46 @@ static int UnwindImpl(void** result, uintptr_t* frames, int* sizes,
6291 if (recursive || disable_stacktraces.load (std ::memory_order_relaxed)) {
6392 return 0 ;
6493 }
65- ++ recursive;
94+ if (ABSL_INTERNAL_BACKTRACE_AVAILABLE ()) {
95+ ++ recursive;
6696
67- static_cast< void> (ucp); // Unused.
68- static const int kStackLength = 64 ;
69- void * stack[kStackLength];
70- int size;
97+ static_cast< void> (ucp); // Unused.
98+ static const int kStackLength = 64 ;
99+ void * stack[kStackLength];
100+ int size;
71101
72- size = backtrace (stack, kStackLength);
73- skip_count++ ; // we want to skip the current frame as well
74- int result_count = size - skip_count;
75- if (result_count < 0 )
76- result_count = 0 ;
77- if (result_count > max_depth)
78- result_count = max_depth;
79- for (int i = 0 ; i < result_count; i++ )
80- result[i] = stack[i + skip_count];
102+ size = backtrace (stack, kStackLength);
103+ skip_count++ ; // we want to skip the current frame as well
104+ int result_count = size - skip_count;
105+ if (result_count < 0 )
106+ result_count = 0 ;
107+ if (result_count > max_depth)
108+ result_count = max_depth;
109+ for (int i = 0 ; i < result_count; i++ )
110+ result[i] = stack[i + skip_count];
81111
82- if (IS_STACK_FRAMES) {
83- // No implementation for finding out the stack frames yet.
84- if (frames ! = nullptr) {
85- memset (frames, 0 , sizeof (* frames) * static_cast< size_t> (result_count));
86- }
87- if (sizes ! = nullptr) {
88- memset (sizes, 0 , sizeof (* sizes) * static_cast< size_t> (result_count));
112+ if (IS_STACK_FRAMES) {
113+ // No implementation for finding out the stack frames yet.
114+ if (frames ! = nullptr) {
115+ memset (frames, 0 , sizeof (* frames) * static_cast< size_t> (result_count));
116+ }
117+ if (sizes ! = nullptr) {
118+ memset (sizes, 0 , sizeof (* sizes) * static_cast< size_t> (result_count));
119+ }
89120 }
90- }
91- if (min_dropped_frames ! = nullptr ) {
92- if ( size - skip_count - max_depth > 0 ) {
93- * min_dropped_frames = size - skip_count - max_depth;
94- } else {
95- * min_dropped_frames = 0 ;
121+ if (min_dropped_frames ! = nullptr) {
122+ if (size - skip_count - max_depth > 0 ) {
123+ * min_dropped_frames = size - skip_count - max_depth;
124+ } else {
125+ * min_dropped_frames = 0 ;
126+ }
96127 }
97- }
98128
99- -- recursive;
129+ -- recursive;
100130
101- return result_count;
131+ return result_count;
132+ }
133+ return 0 ;
102134}
103135
104136namespace absl {
0 commit comments