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 20namespace { 21 22struct 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 53namespace v8 { 54namespace base { 55namespace debug { 56 57bool 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, NULL) == 0); 67} 68 69void DisableSignalStackDump() { 70} 71 72StackTrace::StackTrace() { 73 StackCrawlState state(reinterpret_cast<uintptr_t*>(trace_), kMaxTraces); 74 _Unwind_Backtrace(&TraceStackFrame, &state); 75 count_ = state.frame_count; 76} 77 78void StackTrace::Print() const { 79 std::string backtrace = ToString(); 80 OS::Print("%s\n", backtrace.c_str()); 81} 82 83void 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