1*9356374aSAndroid Build Coastguard Worker// Copyright 2017 The Abseil Authors. 2*9356374aSAndroid Build Coastguard Worker// 3*9356374aSAndroid Build Coastguard Worker// Licensed under the Apache License, Version 2.0 (the "License"); 4*9356374aSAndroid Build Coastguard Worker// you may not use this file except in compliance with the License. 5*9356374aSAndroid Build Coastguard Worker// You may obtain a copy of the License at 6*9356374aSAndroid Build Coastguard Worker// 7*9356374aSAndroid Build Coastguard Worker// https://www.apache.org/licenses/LICENSE-2.0 8*9356374aSAndroid Build Coastguard Worker// 9*9356374aSAndroid Build Coastguard Worker// Unless required by applicable law or agreed to in writing, software 10*9356374aSAndroid Build Coastguard Worker// distributed under the License is distributed on an "AS IS" BASIS, 11*9356374aSAndroid Build Coastguard Worker// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*9356374aSAndroid Build Coastguard Worker// See the License for the specific language governing permissions and 13*9356374aSAndroid Build Coastguard Worker// limitations under the License. 14*9356374aSAndroid Build Coastguard Worker// 15*9356374aSAndroid Build Coastguard Worker// Portable implementation - just use glibc 16*9356374aSAndroid Build Coastguard Worker// 17*9356374aSAndroid Build Coastguard Worker// Note: The glibc implementation may cause a call to malloc. 18*9356374aSAndroid Build Coastguard Worker// This can cause a deadlock in HeapProfiler. 19*9356374aSAndroid Build Coastguard Worker 20*9356374aSAndroid Build Coastguard Worker#ifndef ABSL_DEBUGGING_INTERNAL_STACKTRACE_GENERIC_INL_H_ 21*9356374aSAndroid Build Coastguard Worker#define ABSL_DEBUGGING_INTERNAL_STACKTRACE_GENERIC_INL_H_ 22*9356374aSAndroid Build Coastguard Worker 23*9356374aSAndroid Build Coastguard Worker#include <execinfo.h> 24*9356374aSAndroid Build Coastguard Worker#include <atomic> 25*9356374aSAndroid Build Coastguard Worker#include <cstring> 26*9356374aSAndroid Build Coastguard Worker 27*9356374aSAndroid Build Coastguard Worker#include "absl/debugging/stacktrace.h" 28*9356374aSAndroid Build Coastguard Worker#include "absl/base/attributes.h" 29*9356374aSAndroid Build Coastguard Worker 30*9356374aSAndroid Build Coastguard Worker// Sometimes, we can try to get a stack trace from within a stack 31*9356374aSAndroid Build Coastguard Worker// trace, because we don't block signals inside this code (which would be too 32*9356374aSAndroid Build Coastguard Worker// expensive: the two extra system calls per stack trace do matter here). 33*9356374aSAndroid Build Coastguard Worker// That can cause a self-deadlock. 34*9356374aSAndroid Build Coastguard Worker// Protect against such reentrant call by failing to get a stack trace. 35*9356374aSAndroid Build Coastguard Worker// 36*9356374aSAndroid Build Coastguard Worker// We use __thread here because the code here is extremely low level -- it is 37*9356374aSAndroid Build Coastguard Worker// called while collecting stack traces from within malloc and mmap, and thus 38*9356374aSAndroid Build Coastguard Worker// can not call anything which might call malloc or mmap itself. 39*9356374aSAndroid Build Coastguard Workerstatic __thread int recursive = 0; 40*9356374aSAndroid Build Coastguard Worker 41*9356374aSAndroid Build Coastguard Worker// The stack trace function might be invoked very early in the program's 42*9356374aSAndroid Build Coastguard Worker// execution (e.g. from the very first malloc if using tcmalloc). Also, the 43*9356374aSAndroid Build Coastguard Worker// glibc implementation itself will trigger malloc the first time it is called. 44*9356374aSAndroid Build Coastguard Worker// As such, we suppress usage of backtrace during this early stage of execution. 45*9356374aSAndroid Build Coastguard Workerstatic std::atomic<bool> disable_stacktraces(true); // Disabled until healthy. 46*9356374aSAndroid Build Coastguard Worker// Waiting until static initializers run seems to be late enough. 47*9356374aSAndroid Build Coastguard Worker// This file is included into stacktrace.cc so this will only run once. 48*9356374aSAndroid Build Coastguard WorkerABSL_ATTRIBUTE_UNUSED static int stacktraces_enabler = []() { 49*9356374aSAndroid Build Coastguard Worker void* unused_stack[1]; 50*9356374aSAndroid Build Coastguard Worker // Force the first backtrace to happen early to get the one-time shared lib 51*9356374aSAndroid Build Coastguard Worker // loading (allocation) out of the way. After the first call it is much safer 52*9356374aSAndroid Build Coastguard Worker // to use backtrace from a signal handler if we crash somewhere later. 53*9356374aSAndroid Build Coastguard Worker backtrace(unused_stack, 1); 54*9356374aSAndroid Build Coastguard Worker disable_stacktraces.store(false, std::memory_order_relaxed); 55*9356374aSAndroid Build Coastguard Worker return 0; 56*9356374aSAndroid Build Coastguard Worker}(); 57*9356374aSAndroid Build Coastguard Worker 58*9356374aSAndroid Build Coastguard Workertemplate <bool IS_STACK_FRAMES, bool IS_WITH_CONTEXT> 59*9356374aSAndroid Build Coastguard Workerstatic int UnwindImpl(void** result, int* sizes, int max_depth, int skip_count, 60*9356374aSAndroid Build Coastguard Worker const void *ucp, int *min_dropped_frames) { 61*9356374aSAndroid Build Coastguard Worker if (recursive || disable_stacktraces.load(std::memory_order_relaxed)) { 62*9356374aSAndroid Build Coastguard Worker return 0; 63*9356374aSAndroid Build Coastguard Worker } 64*9356374aSAndroid Build Coastguard Worker ++recursive; 65*9356374aSAndroid Build Coastguard Worker 66*9356374aSAndroid Build Coastguard Worker static_cast<void>(ucp); // Unused. 67*9356374aSAndroid Build Coastguard Worker static const int kStackLength = 64; 68*9356374aSAndroid Build Coastguard Worker void * stack[kStackLength]; 69*9356374aSAndroid Build Coastguard Worker int size; 70*9356374aSAndroid Build Coastguard Worker 71*9356374aSAndroid Build Coastguard Worker size = backtrace(stack, kStackLength); 72*9356374aSAndroid Build Coastguard Worker skip_count++; // we want to skip the current frame as well 73*9356374aSAndroid Build Coastguard Worker int result_count = size - skip_count; 74*9356374aSAndroid Build Coastguard Worker if (result_count < 0) 75*9356374aSAndroid Build Coastguard Worker result_count = 0; 76*9356374aSAndroid Build Coastguard Worker if (result_count > max_depth) 77*9356374aSAndroid Build Coastguard Worker result_count = max_depth; 78*9356374aSAndroid Build Coastguard Worker for (int i = 0; i < result_count; i++) 79*9356374aSAndroid Build Coastguard Worker result[i] = stack[i + skip_count]; 80*9356374aSAndroid Build Coastguard Worker 81*9356374aSAndroid Build Coastguard Worker if (IS_STACK_FRAMES) { 82*9356374aSAndroid Build Coastguard Worker // No implementation for finding out the stack frame sizes yet. 83*9356374aSAndroid Build Coastguard Worker memset(sizes, 0, sizeof(*sizes) * static_cast<size_t>(result_count)); 84*9356374aSAndroid Build Coastguard Worker } 85*9356374aSAndroid Build Coastguard Worker if (min_dropped_frames != nullptr) { 86*9356374aSAndroid Build Coastguard Worker if (size - skip_count - max_depth > 0) { 87*9356374aSAndroid Build Coastguard Worker *min_dropped_frames = size - skip_count - max_depth; 88*9356374aSAndroid Build Coastguard Worker } else { 89*9356374aSAndroid Build Coastguard Worker *min_dropped_frames = 0; 90*9356374aSAndroid Build Coastguard Worker } 91*9356374aSAndroid Build Coastguard Worker } 92*9356374aSAndroid Build Coastguard Worker 93*9356374aSAndroid Build Coastguard Worker --recursive; 94*9356374aSAndroid Build Coastguard Worker 95*9356374aSAndroid Build Coastguard Worker return result_count; 96*9356374aSAndroid Build Coastguard Worker} 97*9356374aSAndroid Build Coastguard Worker 98*9356374aSAndroid Build Coastguard Workernamespace absl { 99*9356374aSAndroid Build Coastguard WorkerABSL_NAMESPACE_BEGIN 100*9356374aSAndroid Build Coastguard Workernamespace debugging_internal { 101*9356374aSAndroid Build Coastguard Workerbool StackTraceWorksForTest() { 102*9356374aSAndroid Build Coastguard Worker return true; 103*9356374aSAndroid Build Coastguard Worker} 104*9356374aSAndroid Build Coastguard Worker} // namespace debugging_internal 105*9356374aSAndroid Build Coastguard WorkerABSL_NAMESPACE_END 106*9356374aSAndroid Build Coastguard Worker} // namespace absl 107*9356374aSAndroid Build Coastguard Worker 108*9356374aSAndroid Build Coastguard Worker#endif // ABSL_DEBUGGING_INTERNAL_STACKTRACE_GENERIC_INL_H_ 109