1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // Slightly adapted for inclusion in V8. 6 // Copyright 2016 the V8 project authors. All rights reserved. 7 8 #include "src/base/debug/stack_trace.h" 9 10 #include <signal.h> 11 #include <stddef.h> 12 #include <string.h> 13 #include <unwind.h> 14 15 #include <src/base/platform/platform.h> 16 17 #include <iomanip> 18 #include <ostream> 19 20 namespace { 21 22 struct StackCrawlState { 23 StackCrawlState(uintptr_t* frames, size_t max_depth) 24 : frames(frames), 25 frame_count(0), 26 max_depth(max_depth), 27 have_skipped_self(false) {} 28 29 uintptr_t* frames; 30 size_t frame_count; 31 size_t max_depth; 32 bool have_skipped_self; 33 }; 34 35 _Unwind_Reason_Code TraceStackFrame(_Unwind_Context* context, void* arg) { 36 StackCrawlState* state = static_cast<StackCrawlState*>(arg); 37 uintptr_t ip = _Unwind_GetIP(context); 38 39 // The first stack frame is this function itself. Skip it. 40 if (ip != 0 && !state->have_skipped_self) { 41 state->have_skipped_self = true; 42 return _URC_NO_REASON; 43 } 44 45 state->frames[state->frame_count++] = ip; 46 if (state->frame_count >= state->max_depth) 47 return _URC_END_OF_STACK; 48 return _URC_NO_REASON; 49 } 50 51 } // namespace 52 53 namespace v8 { 54 namespace base { 55 namespace debug { 56 57 bool EnableInProcessStackDumping() { 58 // When running in an application, our code typically expects SIGPIPE 59 // to be ignored. Therefore, when testing that same code, it should run 60 // with SIGPIPE ignored as well. 61 // TODO(phajdan.jr): De-duplicate this SIGPIPE code. 62 struct sigaction action; 63 memset(&action, 0, sizeof(action)); 64 action.sa_handler = SIG_IGN; 65 sigemptyset(&action.sa_mask); 66 return (sigaction(SIGPIPE, &action, nullptr) == 0); 67 } 68 69 void DisableSignalStackDump() { 70 } 71 72 StackTrace::StackTrace() { 73 StackCrawlState state(reinterpret_cast<uintptr_t*>(trace_), kMaxTraces); 74 _Unwind_Backtrace(&TraceStackFrame, &state); 75 count_ = state.frame_count; 76 } 77 78 void StackTrace::Print() const { 79 std::string backtrace = ToString(); 80 OS::Print("%s\n", backtrace.c_str()); 81 } 82 83 void StackTrace::OutputToStream(std::ostream* os) const { 84 for (size_t i = 0; i < count_; ++i) { 85 *os << "#" << std::setw(2) << i << trace_[i] << "\n"; 86 } 87 } 88 89 } // namespace debug 90 } // namespace base 91 } // namespace v8 92