Warning, /include/absl/debugging/internal/stacktrace_emscripten-inl.inc is written in an unsupported language. File is not indexed.
0001 // Copyright 2017 The Abseil Authors.
0002 //
0003 // Licensed under the Apache License, Version 2.0 (the "License");
0004 // you may not use this file except in compliance with the License.
0005 // You may obtain a copy of the License at
0006 //
0007 // https://www.apache.org/licenses/LICENSE-2.0
0008 //
0009 // Unless required by applicable law or agreed to in writing, software
0010 // distributed under the License is distributed on an "AS IS" BASIS,
0011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0012 // See the License for the specific language governing permissions and
0013 // limitations under the License.
0014 //
0015 // Portable implementation - just use glibc
0016 //
0017 // Note: The glibc implementation may cause a call to malloc.
0018 // This can cause a deadlock in HeapProfiler.
0019
0020 #ifndef ABSL_DEBUGGING_INTERNAL_STACKTRACE_EMSCRIPTEN_INL_H_
0021 #define ABSL_DEBUGGING_INTERNAL_STACKTRACE_EMSCRIPTEN_INL_H_
0022
0023 #include <emscripten.h>
0024
0025 #include <atomic>
0026 #include <cstring>
0027
0028 #include "absl/base/attributes.h"
0029 #include "absl/debugging/stacktrace.h"
0030
0031 extern "C" {
0032 uintptr_t emscripten_stack_snapshot();
0033 uint32_t emscripten_stack_unwind_buffer(uintptr_t pc, void *buffer,
0034 uint32_t depth);
0035 }
0036
0037 // Sometimes, we can try to get a stack trace from within a stack
0038 // trace, which can cause a self-deadlock.
0039 // Protect against such reentrant call by failing to get a stack trace.
0040 //
0041 // We use __thread here because the code here is extremely low level -- it is
0042 // called while collecting stack traces from within malloc and mmap, and thus
0043 // can not call anything which might call malloc or mmap itself.
0044 static __thread int recursive = 0;
0045
0046 // The stack trace function might be invoked very early in the program's
0047 // execution (e.g. from the very first malloc).
0048 // As such, we suppress usage of backtrace during this early stage of execution.
0049 static std::atomic<bool> disable_stacktraces(true); // Disabled until healthy.
0050 // Waiting until static initializers run seems to be late enough.
0051 // This file is included into stacktrace.cc so this will only run once.
0052 ABSL_ATTRIBUTE_UNUSED static int stacktraces_enabler = []() {
0053 // Check if we can even create stacktraces. If not, bail early and leave
0054 // disable_stacktraces set as-is.
0055 // clang-format off
0056 if (!EM_ASM_INT({ return (typeof wasmOffsetConverter !== 'undefined'); })) {
0057 return 0;
0058 }
0059 // clang-format on
0060 disable_stacktraces.store(false, std::memory_order_relaxed);
0061 return 0;
0062 }();
0063
0064 template <bool IS_STACK_FRAMES, bool IS_WITH_CONTEXT>
0065 static int UnwindImpl(void **result, int *sizes, int max_depth, int skip_count,
0066 const void *ucp, int *min_dropped_frames) {
0067 if (recursive || disable_stacktraces.load(std::memory_order_relaxed)) {
0068 return 0;
0069 }
0070 ++recursive;
0071
0072 static_cast<void>(ucp); // Unused.
0073 constexpr int kStackLength = 64;
0074 void *stack[kStackLength];
0075
0076 int size;
0077 uintptr_t pc = emscripten_stack_snapshot();
0078 size = emscripten_stack_unwind_buffer(pc, stack, kStackLength);
0079
0080 int result_count = size - skip_count;
0081 if (result_count < 0) result_count = 0;
0082 if (result_count > max_depth) result_count = max_depth;
0083 for (int i = 0; i < result_count; i++) result[i] = stack[i + skip_count];
0084
0085 if (IS_STACK_FRAMES) {
0086 // No implementation for finding out the stack frame sizes yet.
0087 memset(sizes, 0, sizeof(*sizes) * result_count);
0088 }
0089 if (min_dropped_frames != nullptr) {
0090 if (size - skip_count - max_depth > 0) {
0091 *min_dropped_frames = size - skip_count - max_depth;
0092 } else {
0093 *min_dropped_frames = 0;
0094 }
0095 }
0096
0097 --recursive;
0098
0099 return result_count;
0100 }
0101
0102 namespace absl {
0103 ABSL_NAMESPACE_BEGIN
0104 namespace debugging_internal {
0105 bool StackTraceWorksForTest() { return true; }
0106 } // namespace debugging_internal
0107 ABSL_NAMESPACE_END
0108 } // namespace absl
0109
0110 #endif // ABSL_DEBUGGING_INTERNAL_STACKTRACE_EMSCRIPTEN_INL_H_