Back to home page

EIC code displayed by LXR

 
 

    


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_